问:
在cmd.exe下运行rundll32.exe mydll.dll,MyFunc ,本想直接在当前cmd窗口输出调试信息.
可因rundll32是Win32 GUI程序而非Win32 console,所以cmd.exe标准输入输出句柄无法被mydll.dll继承用来向父进程cmd.exe输出数据.
这时, 如果用强行用GetStdHandle获得句柄,然后用WriteConsole来进行输出,则会发生无效句柄错误.
但是如果在这之前先AllocConsole,则可正常WriteConsole,但是会新建个控制台窗口来输出数据,很不爽 :-P
有没有什么办法向当前cmd.exe窗口输出数据呢?
我想通过给进程拍照和遍历,
可以获得rundll32的父进程cmd.exe的PID和Handle,但如何进一步下去(建立管道, 写数据)就没辙了?
不知道有没有描述清楚 还是太罗嗦了,麻烦大家看看,谢谢~
答:
如果只是要输出数据的话 可以向父窗口 发送键盘消息 WM_CHAR 输出你的数据
代码
Code:
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved )
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
ShowMe();
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
void ShowMe()
{
DWORD dwProcID;
HWND hWnd;
dwProcID = FindParentProcID(GetCurrentProcessId());
sprintf(buf, "dwProcID:%d/nProcessId:%d ", dwProcID, GetCurrentProcessId());
MessageBox (NULL, buf, "提示", MB_ICONERROR);
if(dwProcID == -1)
return;
hWnd = GetProcessMainWnd(dwProcID);
if(hWnd ==NULL)
return;
SendMessage(hWnd, WM_CHAR, WPARAM('Z'), NULL);
}
Code:
DWORD FindParentProcID(DWORD dwChildProcID) //找到返回父进程PID, 找不到返回-1
{
PROCESSENTRY32 pr32 = {0};
pr32.dwSize = sizeof(PROCESSENTRY32); // 不要漏了这句
// 提权先
DebugPrivilege(SE_DEBUG_NAME, TRUE);
// 给进程照相
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
// 拍照失败, 返回-1
if (hSnap == (HANDLE)-1) return (DWORD)-1;
// 开始枚举...
if (Process32First(hSnap,&pr32) == FALSE)
{
CloseHandle( hSnap );
return (DWORD)-1;
}
do
{
if( pr32.th32ProcessID == dwChildProcID)
{ // 如果被枚举到的进程ID等于所给的ID, 则返回父进程ID
CloseHandle( hSnap );
return pr32.th32ParentProcessID;
}
}
while( Process32Next(hSnap, &pr32));
// 找不到父进程ID, 返回-1
CloseHandle(hSnap);
return -1;
}
Code:
typedef struct tagWNDINFO
{
DWORD dwProcessId;
HWND hWnd;
} WNDINFO, *LPWNDINFO;
BOOL CALLBACK YourEnumProc(HWND hWnd,LPARAM lParam)
{
DWORD dwProcessId;
GetWindowThreadProcessId(hWnd, &dwProcessId);
LPWNDINFO pInfo = (LPWNDINFO)lParam;
if(dwProcessId == pInfo->dwProcessId)
{
pInfo->hWnd = hWnd;
return FALSE;
}
return TRUE;
}
HWND GetProcessMainWnd(DWORD dwProcessId) // 找到返回进程主窗口的hWnd, 如果没有,返回NULL
{
WNDINFO wi;
wi.dwProcessId = dwProcessId;
wi.hWnd = NULL;
EnumWindows(YourEnumProc,(LPARAM)&wi);
return wi.hWnd;
}