最近需要在程序中以管理员身份运行某程序,尝试了发现下面几种方法
1、系统自带命令runas,无法实现自动输入密码
2、sanur第三方小工具通过管道和runas交互实现自动输入密码,在Win7和Window2008上无法正常工作
3、自己通过编程实现runas的功能,短时间开发并调试完成较困难
最终用使用Detours hook runas的ReadConsole、CreateProcessWithLogonW实现
代码如下:
/*runasdll源码*/
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <stdio.h>
#include "detours.h"
#pragma comment(lib, "detours.lib")
typedef BOOL (WINAPI *pfnReadConsole)(
__in HANDLE hConsoleInput,
__out LPVOID lpBuffer,
__in DWORD nNumberOfCharsToRead,
__out LPDWORD lpNumberOfCharsRead,
__in_opt LPVOID pInputControl
);
typedef BOOL (WINAPI *pfnCreateProcessWithLogonW)(
__in LPCWSTR lpUsername,
__in LPCWSTR lpDomain,
__in LPCWSTR lpPassword,
__in DWORD dwLogonFlags,
__in LPCWSTR lpApplicationName,
__in LPWSTR lpCommandLine,
__in DWORD dwCreationFlags,
__in LPVOID lpEnvironment,
__in LPCWSTR lpCurrentDirectory,
__in LPSTARTUPINFOW lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInfo
);
BOOL WINAPI MyReadConsole(
__in HANDLE hConsoleInput,
__out LPVOID lpBuffer,
__in DWORD nNumberOfCharsToRead,
__out LPDWORD lpNumberOfCharsRead,
__in_opt LPVOID pInputControl
);
BOOL WINAPI MyCreateProcessWithLogonW(
__in LPCWSTR lpUsername,
__in LPCWSTR lpDomain,
__in LPCWSTR lpPassword,
__in DWORD dwLogonFlags,
__in LPCWSTR lpApplicationName,
__in LPWSTR lpCommandLine,
__in DWORD dwCreationFlags,
__in LPVOID lpEnvironment,
__in LPCWSTR lpCurrentDirectory,
__in LPSTARTUPINFOW lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInfo
);
BOOL MByteToWChar(LPCSTR lpcszStr, LPWSTR lpwszStr, DWORD dwSize);
pfnReadConsole realReadConsole = (pfnReadConsole)GetProcAddress(LoadLibrary("Kernel32.dll"), "ReadConsoleW");
pfnCreateProcessWithLogonW realCreateProcessWithLogonW = (pfnCreateProcessWithLogonW)GetProcAddress(LoadLibrary("Advapi32.dll"), "CreateProcessWithLogonW");
HANDLE g_hDLL = NULL;
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
char szModuleName[MAX_PATH] = {0};
char szExe[MAX_PATH] = {0};
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
g_hDLL = hModule;
GetModuleFileName(NULL, szModuleName, MAX_PATH-1);
strcpy(szExe, strrchr(szModuleName, '\\')+1);
if (strcmpi(szExe, "RUNAS.EXE"))
{
return TRUE;
}
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach((PVOID*)&realReadConsole, MyReadConsole);
DetourAttach((PVOID*)&realCreateProcessWithLogonW, MyCreateProcessWithLogonW);
DetourTransactionCommit();
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
BOOL WINAPI MyReadConsole(
__in HANDLE hConsoleInput,
__out LPVOID lpBuffer,
__in DWORD nNumberOfCharsToRead,
__out LPDWORD lpNumberOfCharsRead,
__in_opt LPVOID pInputControl
)
{
*((char*)lpBuffer) = 0x0d;
*lpNumberOfCharsRead = 1;
return FALSE;
}
BOOL WINAPI MyCreateProcessWithLogonW(
__in LPCWSTR lpUsername,
__in LPCWSTR lpDomain,
__in LPCWSTR lpPassword,
__in DWORD dwLogonFlags,
__in LPCWSTR lpApplicationName,
__in LPWSTR lpCommandLine,
__in DWORD dwCreationFlags,
__in LPVOID lpEnvironment,
__in LPCWSTR lpCurrentDirectory,
__in LPSTARTUPINFOW lpStartupInfo,
__out LPPROCESS_INFORMATION lpProcessInfo
)
{
WCHAR wcsPassword[128] = {0};
char szPassword[128] = {0};
char szIniFile[MAX_PATH] = {0};
GetModuleFileName((HMODULE)g_hDLL, szIniFile, MAX_PATH);
strcpy(strrchr(szIniFile, '\\')+1, "MyRunas.ini");
GetPrivateProfileString("Setting", "password", "", szPassword, 128, szIniFile);
if (!strlen(szPassword))
{
printf("读取密码文件%s失败,请检查设置是否正确!\n", szIniFile);
MessageBox(NULL, "读取密码文件失败,请检查设置是否正确!", "", NULL);
}
else
{
MByteToWChar(szPassword, wcsPassword, sizeof(wcsPassword)/sizeof(wcsPassword[0]));
}
return realCreateProcessWithLogonW(lpUsername,
lpDomain,
wcsPassword,
dwLogonFlags,
lpApplicationName,
lpCommandLine,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInfo);
}
BOOL MByteToWChar(LPCSTR lpcszStr, LPWSTR lpwszStr, DWORD dwSize)
{
// Get the required size of the buffer that receives the Unicode
// string.
DWORD dwMinSize;
dwMinSize = MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, NULL, 0);
if(dwSize < dwMinSize)
{
return FALSE;
}
// Convert headers from ASCII to Unicode.
MultiByteToWideChar (CP_ACP, 0, lpcszStr, -1, lpwszStr, dwMinSize);
return TRUE;
}
//detours需要dll导出任意一个函数
VOID test()
{
}
/*MyRunas源码*/
// myrunas.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <windows.h>
#include "detours.h"
#pragma comment(lib, "detours.lib")
int _tmain(int argc, _TCHAR* argv[])
{
if (argc==1)
{
char szInfo[1024] = {0};
wsprintf(szInfo, "%s", "MyRunas只是一个外壳,在启动runas时修改了它的某些代码,使其支持自动输入密码,其中密码是在MyRunas.ini文件中设置的,除此之外MyRunas用法和runas命令完全相同。"
"在XP、Win7、Win2008下测试通过。\n\nMyRunas v1.0 2014/3\nby YangFan\nEmail:522419441@qq.com", "MyRunas");
MessageBox(GetForegroundWindow(), szInfo, "MyRunas", MB_ICONINFORMATION);
return -1;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
memset(&si, 0, sizeof(si) );
memset( &pi,0, sizeof(pi) );
char szMyRunasCMDLine[1024] = {0};
char szRunasCMDLine[1024] = {0};
strcpy(szMyRunasCMDLine, GetCommandLine());
strcpy(szRunasCMDLine, "runas ");
strcat(szRunasCMDLine, strstr(szMyRunasCMDLine+strlen(__argv[0]), __argv[1]));
char szDLL[MAX_PATH] = {0};
GetModuleFileName(NULL, szDLL, 1024);
strcpy(strrchr(szDLL, '\\')+1, "runasdll.dll");///runasdll.dll必须要导出函数,否则会报错
// Start the child process.
if( !DetourCreateProcessWithDll( NULL, // No module name (use command line)
szRunasCMDLine, // Command line
NULL, // Process handle not inheritable
NULL, // Thread handle not inheritable
FALSE, // Set handle inheritance to FALSE
0, // No creation flags
NULL, // Use parent's environment block
NULL, // Use parent's starting directory
&si, // Pointer to STARTUPINFO structure
&pi,
szDLL,
NULL)
)
{
printf( "CreateProcess failed (%d)\n", GetLastError() );
return -1;
}
// Wait until child process exits.
WaitForSingleObject( pi.hProcess, INFINITE );
// Close process and thread handles.
CloseHandle( pi.hProcess );
CloseHandle( pi.hThread );
return 0;
}
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界