现在有个编译好的exe文件,我想让它运行时能使用当前目录下的一个dll文件,不需要指定调用这个dll中的哪个函数,因为已经有脚本写好了,现在只需要让这个程序运行时同时运行那个dll就行。有什么方法能实现?

解决方案 »

  1.   

    暂停的方式创建进程, 创建远线程去Load Dll, 再恢复线程
    BOOL RunWithDll(char * pRunCmd, char * pDllPath)
    {
    char * pCmd = NULL;
    char * pCurDir = NULL;
    BOOL bPart = FALSE;
    char  szCurDir[1024];
    DWORD dwLen;
    DWORD i;
    while(*pRunCmd == ' ') pRunCmd++;
    dwLen = (DWORD)strlen(pRunCmd);
    for(i=0; i<dwLen; i++)
    {
    if(pRunCmd[i] == ' ' && bPart == FALSE)
    {
    pCmd = pRunCmd + i;
    break;
    }
    if(pRunCmd[i] == '"')
    {
    if(bPart) bPart = FALSE;
    else bPart = TRUE;
    }
    }
    if(pCmd == NULL)
    {
    pCmd = pRunCmd;
    }
    for(; i>0; i--)
    {
    if(pRunCmd[i] == '\\')
    {
    memset(szCurDir, 0, sizeof(szCurDir));
    if(pRunCmd[0] == '"')
    {
    strncpy(szCurDir, pRunCmd+1, i-1);
    szCurDir[i-1] = 0;
    }
    else
    {
    strncpy(szCurDir, pRunCmd  , i  );
    szCurDir[i] = 0;
    }
    pCurDir = szCurDir;
    break;
    }
    }
    // MsgA("pCmd:%s\r\npCurDir:%s", pCmd, pCurDir);
    PROCESS_INFORMATION ProcessInfo; 
    STARTUPINFOA StartupInfo;
    ZeroMemory(&StartupInfo, sizeof(StartupInfo));
    StartupInfo.cb = sizeof(StartupInfo); //Only compulsory field
    StartupInfo.wShowWindow = SW_SHOW; //windows media player not show
    StartupInfo.dwFlags = STARTF_USESHOWWINDOW;
    if(CreateProcessA(NULL, pRunCmd, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL,
    pCurDir, &StartupInfo, &ProcessInfo) == FALSE)
    {
    return FALSE;
    }
    if(ProcRemtLoadDll(ProcessInfo.hProcess, pDllPath) == FALSE)
    {
    ::ResumeThread(ProcessInfo.hThread);
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ProcessInfo.hProcess);
    return FALSE;
    }
    ::ResumeThread(ProcessInfo.hThread); //CREATE_SUSPENDED  for wait the dll load done
    CloseHandle(ProcessInfo.hThread);
    CloseHandle(ProcessInfo.hProcess);
    return TRUE;
    }HMODULE ProcRemtLoadDll(HANDLE hProc, char * pDllPath)
    {
    BYTE Code[0x20]; //00
    HMODULE hModule; //20
    int nError; //24 //28 :pDllPath
    DWORD   dwSize = 0x20+4+4+1024, dwNedsize;
    char * plibstr;
    BOOL    bRet;
    Fun1 pFunLoadLib;
    HANDLE thd_hd;
    pFunLoadLib = (Fun1)::GetProcAddress(::GetModuleHandle(_T("Kernel32")), "LoadLibraryA");
    if(pFunLoadLib == NULL)
    return NULL;
    plibstr =(char *)VirtualAllocEx(hProc, 0, dwSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    if(plibstr == NULL)
    return NULL;
    CreateThreadFun1(Code, (DWORD)plibstr, (DWORD)pFunLoadLib, (LPDWORD)(plibstr+0x20), (LPDWORD)(plibstr+0x24));
    dwNedsize = 0x20;
    bRet = WriteProcessMemory(hProc, plibstr, Code, dwNedsize, &dwSize); //复制代码
    if(bRet == FALSE || dwSize != dwNedsize )
    {
    VirtualFreeEx(hProc, plibstr, 0, MEM_RELEASE );
    return NULL;
    }
    dwNedsize = (DWORD)strlen(pDllPath) + 1;
    bRet = WriteProcessMemory(hProc, plibstr+0x28, pDllPath, dwNedsize, &dwSize); //复制参数
    if(bRet == FALSE || dwSize != dwNedsize )
    {
    VirtualFreeEx(hProc, plibstr, 0, MEM_RELEASE );
    return NULL;
    }
    thd_hd = ::CreateRemoteThread(hProc, 0, 0, (LPTHREAD_START_ROUTINE)plibstr, (void *)(plibstr+0x28), NULL, NULL);
    if(thd_hd == NULL)
    {
    VirtualFreeEx(hProc, plibstr, 0, MEM_RELEASE);
    return NULL;
    }
    WaitForSingleObject(thd_hd,INFINITE);
    CloseHandle(thd_hd);
    dwNedsize = 4;
    bRet = ::ReadProcessMemory(hProc, plibstr+0x20, &hModule, dwNedsize, &dwSize);
    if(bRet == FALSE || dwSize != dwNedsize )
    {
    VirtualFreeEx(hProc, plibstr, 0, MEM_RELEASE);
    return NULL;
    }
    if(hModule == NULL)
    {
    bRet = ::ReadProcessMemory(hProc, plibstr+0x24, &nError , dwNedsize, &dwSize);
    if(bRet == FALSE || dwSize != dwNedsize )
    {
    VirtualFreeEx(hProc, plibstr, 0, MEM_RELEASE);
    return NULL;
    }
    ::SetLastError(nError);
    }
    bRet = VirtualFreeEx(hProc, plibstr, 0, MEM_RELEASE);
    if(bRet == FALSE)
    return NULL;
    return hModule;
    }LPBYTE CreateThreadFun1(LPBYTE pCode, DWORD dwCodeAdr, DWORD dwCallFunAdr, LPDWORD pFunRetVal, LPDWORD pError)
    {
    DWORD dwFunError;
    dwFunError = (DWORD)&GetLastError;
    *(DWORD *)(pCode + 0x00) = 0x042474FF; //push d,[esp+04]
    *( BYTE *)(pCode + 0x04) = 0xE8; //Call *(DWORD *)(pCode + 0x05) = dwCallFunAdr - (4+5); //            Fun相对地址
    *(DWORD *)(pCode + 0x05) = dwCallFunAdr - (dwCodeAdr+0x04+5);// dwCallFunAdr相对地址
    *( BYTE *)(pCode + 0x09) = 0xA3; //mov [         ],eax
    *(DWORD *)(pCode + 0x0A) = (DWORD)pFunRetVal; //  FunRetVal
    *( BYTE *)(pCode + 0x0E) = 0xE8; //Call
    *(DWORD *)(pCode + 0x0F) = dwFunError -   (dwCodeAdr+0x0E+5);// GetLastError相对地址
    *( BYTE *)(pCode + 0x13) = 0xA3; //mov [      ],eax
    *(DWORD *)(pCode + 0x14) = (DWORD)pError; //  pError
    *( BYTE *)(pCode + 0x18) = 0xC2; //retn
    *( WORD *)(pCode + 0x19) = 0x0004; // 04  //一个参数返回
    *( WORD *)(pCode + 0x1B) = 0xCC; //int 3
    return pCode;
    }
      

  2.   

    已经编译好的exe不修改的话是无论如何都不能调用你随便指定的一个dll的。你说的脚本写好了,写好了给谁用?要么修改代码重新编译这个exe,要么用另一个程序采用楼上类似的方法注入指定的dll。
      

  3.   

    简单一点的,你把要使用的DLL的路径写在配置文件里
      

  4.   

    使用PE注入技术。编写自定位代码装载DLL,将代码添加到新的节区里面先于原程序运行。你的代码在原程序的进程空间运行,不必远程注入了;不过,PE注入实现起来有点麻烦,需要对PE格式有比较详细的了解。还是远程注入吧,相比之下简单多了。
      

  5.   

    “DLLname\0”
    call next
    next: pop eax
    再通过eax减去dll名称长度以及call代码长度,得到dll名称首址
    push eax
    call LoadLibrary
    jmp  0x1234567 (远跳,得到入口后把这个地址用入口地址替换)
    将对应的代码写到数据段空的地方,修改数据段属性为可运行(实际不修改也可以)从PE中找到程序入口,把入口改到你的call next上