2017-09-26 14 views
0

DLL을 생성 했으므로 창에서 rundll32.exe 명령을 사용하여 함수 중 하나를 실행하려고합니다.CreateProcess로 rundll32.exe 실행

rundll32.exe를 사용하면 명령 줄에서 올바르게 실행됩니다. 그러나, 나는 그것을 (rundll32.exe) 별도의 프로그램에서 호출하고 싶습니다. 직접 사용하는 기본 라이브러리 (Easyhook)에서 32/64 비트 호환성 문제로 인해 코드에서 함수를 직접 호출 할 수 없습니다. 다음은

내가 DLL 함수를 실행하기위한 시도로 사용하고 무엇을 :

STARTUPINFO si; 
PROCESS_INFORMATION pi; 

ZeroMemory(&si, sizeof(si)); 
si.cb = sizeof(si); 
ZeroMemory(&pi, sizeof(pi)); 

LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe"; 
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc"; 

BOOL cpRes = CreateProcess(application, 
    cmd, 
    NULL, 
    NULL, 
    FALSE, 
    0, 
    NULL, 
    NULL, 
    &si, 
    &pi); 

if(cpRes == 0) { 
    cout << "ERROR\n"; 
    cout << GetLastError() << endl; 
} else { 
    cout << "DLL Launched!" << endl; 
} 

CloseHandle(pi.hProcess); 
CloseHandle(pi.hThread); 

내 콘솔에 출력은 항상 DLL Launched이다; 그러나 실제로 내 DLL이 실제로 호출되는 효과를 보지 못했습니다 (현재 명령이 파일에 기록하는 방식으로 스텁 아웃 됨).

응용 프로그램을 C:\\Windows\\system32\\notepad.exe과 같은 것으로 바꾸면 프로그램이 성공적으로 실행됩니다.

ofstream file; 
file.open("C:\\Projects\\Test\\test.txt"); 
file << "I wrote to a file!"; 
file.close(); 

Rundll32는 함께 사용할 수없는 이유 CreateProcess를가있다 :

완료, 여기 MyFunc의 몸인가? 이것을 읽는 동안 나는 LoadLibrary()DLLMain에 대한 몇 가지 경고를 발견했으나 처럼 보이지 않습니다.


추가 확인 :
이 현재 (의심) 32 비트 어플리케이션 인 32 비트 rundll32.exe 시작 (로직은 32 또는 64 비트 버전을 호출 나중에 추가 될 것이다).

C:\Windows\system32\rundll32.exe C:\Projects\Test\mydll.dll,MyFunc 

가 예상 결과를 실행

EXPORTS 
    MyFunc 

:도있는 .def 파일이

extern "C" __declspec(dllexport) void CALLBACK MyFunc(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow); 

void CALLBACK MyFunc(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow) { ... } 

을 다음과 같이

내 DLL입니다.


업데이트
NULL-application 설정과 코멘트에 언급 작동하도록 보인다 cmd를에서 rundll32.exe을 포함.

관련 문서 다음 CreateProcess() 문서 당
CreateProcess
RunDll32.exe

+0

이 cout을'의 출력 << GetLastError() << endl의 무엇이며, DLL이 제대로 실행되지 않을 때' ? –

+0

@ NaseefUrRahman 출력은 [0] (https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382(v=vs.85)asp)입니다. – user5786682

+0

DLL에서 호출하려고하는 함수의 정확한 서명은 무엇입니까? –

답변

1

: NULL이 아닌, 널 종료 문자열이 lpApplicationName가 가리키는

모두 lpApplicationName 만약

lpCommandLine가있는 모듈을 지정합니다 를 실행하고 lpCommandLine이 가리키는 널 종료 문자열은 명령 행을 지정합니다.새 프로세스에서는 GetCommandLine을 사용하여 전체 명령 줄을 검색 할 수 있습니다. C로 작성된 콘솔 프로세스는 argcargv 인수를 사용하여 명령 행을 구문 분석 할 수 있습니다. argv[0]은 모듈 이름이므로 C 프로그래머는 일반적으로 모듈 이름을 명령 줄의 첫 번째 토큰으로 반복합니다.

첫 번째 명령 줄 토큰으로 rundll32.exe을 반복하지 않습니다. 이 대신에

LPCTSTR application = "C:\\Windows\\system32\\rundll32.exe"; 
LPTSTR cmd = "C:\\Projects\\Test\\mydll.dll,MyFunc"; 

: 당신이 lpApplicationName 매개 변수를 계속 사용하는 경우

그래서,이 변경은 현재의 미덕에 의해 (ANSI/MBCS 용으로 컴파일

LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe"); 
LPTSTR cmd = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc"); 

주 좁은 문자열을 CreateProcess()으로 전달한다는 사실). 혹시 유니 코드 컴파일 프로젝트를 업데이트하는 경우, 대신 이것을 사용 : 이것은

TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc"); 

을 설명서에 명시 때문에 :

lpCommandLine [에, 밖으로, 선택 사항]
을 ...
이 함수의 유니 코드 버전 CreateProcessW은이 문자열의 내용을 수정할 수 있습니다. 따라서이 매개 변수는 읽기 전용 메모리 (예 : const 변수 또는 리터럴 문자열)에 대한 포인터가 될 수 없습니다. 이 매개 변수가 상수 문자열이면 함수가 액세스 위반을 일으킬 수 있습니다.

심지어 ANSI/MBCS에, 어쨌든 TCHAR[] 배열에 cmd을 변경하는 것이 좋습니다, 그래서 당신은 같은 것을 할 수 있습니다 : 첫 번째 토큰으로 모듈 파일 이름을 전달하여,

LPCTSTR application = TEXT("C:\\Windows\\system32\\rundll32.exe"); 

TCHAR cmd[(MAX_PATH*2)+10]; 
wsprintf(cmd, TEXT("%s %s,%s"), application, TEXT("C:\\Projects\\Test\\mydll.dll"), TEXT("MyFunc")); 

어느 쪽이든을 lpCommandLine 매개 변수에, 당신은 NULL로 lpApplicationName 매개 변수를 설정할 수 있습니다

lpApplicationName 매개 변수는 NULL이 될 수 있습니다. 이 경우 모듈 이름은 lpCommandLine 문자열의 첫 번째 공백으로 구분 된 토큰이어야합니다.

하자 CreateProcess() 설치 올바른 명령 줄은 당신을 위해 rundll32.exe에 전달할 :

TCHAR cmd[] = TEXT("C:\\Windows\\system32\\rundll32.exe C:\\Projects\\Test\\mydll.dll,MyFunc"); 

BOOL cpRes = CreateProcess(NULL, cmd, ...); 
+1

* lpCommandLine *에 토큰. 필수 전체 경로는 아닙니다. 심지어 이름도 아니야. 모든 문자열 (공백 없이는 괜찮습니다). 그래서'@ C : \\ Projects \\ Test \\ mydll.dll, MyFunc'도 작동합니다. 그리고 만약 우리가 정확하게 * lpApplicationName *을 가지고 있다면 항상'CreateProcess'에 패스하는 것이 더 좋다. – RbMm

+1

전반적으로 좋은 대답이지만,'TCHAR cmd [] = ...'를 사용하여 제안한다면, 'TCHAR cmd [] = TEXT ("C : \\ Windows .... \\ mydll.dll, MyFunc");'와 같이 문자열 리터럴 주위의'TEXT' 매크로를 사용하십시오. 대안은'WCHAR'과'L' 접두어를 명시 적으로 사용하는 것입니다. –

+0

@RbMm 규칙 상으로, argv [0]는 호출 프로세스의 전체 경로가 될 것으로 예상됩니다. 물론 모듈 이름 만 전달할 수는 있지만 전체 경로가 필요한 모든 콘솔 앱이 손상 될 수 있습니다. 아마'rundll32'는 그렇지 않습니다. 그것을 위험에 빠뜨리지 마십시오. –