0x01 子进程继承父进程内核对象句柄
#include <Windows.h>
#include <iostream>
#include <strsafe.h>
using namespace std;
int main(int argc, char *argv[])
{
SECURITY_ATTRIBUTES KerObjSec = { 0 };
KerObjSec.bInheritHandle = TRUE;
KerObjSec.nLength = sizeof(KerObjSec); KerObjSec.lpSecurityDescriptor = NULL;
HANDLE KernelObj = CreateMutex(&KerObjSec, TRUE, TEXT("KernelObj"));
WCHAR Program[] = L"D:\test.exe"; WCHAR CmdLine[20] = { 0 };
STARTUPINFO StartUpInfo = { 0 }; PROCESS_INFORMATION ProcessInformation;
StringCchPrintf((STRSAFE_LPWSTR)CmdLine, sizeof(CmdLine) / 2, TEXT("D:\test.exe %x"), KernelObj);
SECURITY_ATTRIBUTES ProcessSec = { 0 }; SECURITY_ATTRIBUTES ThreadSec = { 0 };
ProcessSec.lpSecurityDescriptor = NULL; ProcessSec.nLength = sizeof(ProcessSec);
ProcessSec.bInheritHandle = TRUE;
ThreadSec.lpSecurityDescriptor = NULL; ThreadSec.nLength = sizeof(ThreadSec);
ThreadSec.bInheritHandle = FALSE;
cout << "
开始创建子进程
" << endl;
BOOL Process = CreateProcess((LPCWSTR)&Program, (LPWSTR)&CmdLine, &ProcessSec,
&ThreadSec, TRUE, NULL, NULL, NULL, &StartUpInfo, &ProcessInformation
);
if (Process == 0) cout << "CreateProcess 错误代码: " << GetLastError() << endl;
return 0;
}
#include <Windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[])
{
if (argc == 2)
{
cout << "Now In child process!" << endl;
char Buffer[20] = { 0 }; DWORD FatherHandle = NULL;
memcpy(Buffer, argv[1], 4);
sscanf_s(Buffer, "%x", &FatherHandle);
HANDLE res = (HANDLE)FatherHandle;
if (CloseHandle(res))
cout << "对象句柄已经删除" << endl;
else
cout << "对象句柄不可删除" << endl;
}
return 0;
}
- 当内核对象和子进程都设置为可继承时,子进程才可以操作内核对象
- 反之则不可以
0x02 创建进程间共享内核对象
#include <Windows.h>
#include <iostream>
#include <strsafe.h>
using namespace std;
int main(int argc, char *argv[])
{
SECURITY_ATTRIBUTES KerObjSec = { 0 };
KerObjSec.bInheritHandle = FALSE;
KerObjSec.nLength = sizeof(KerObjSec);
KerObjSec.lpSecurityDescriptor = NULL;
HANDLE KernelObj = CreateMutex(&KerObjSec, TRUE, TEXT("KernelObj-kb5j-bs36-55kv"));
STARTUPINFO StartUpInfo = { 0 }; PROCESS_INFORMATION ProcessInformation;
SECURITY_ATTRIBUTES ProcessSec = { 0 };
SECURITY_ATTRIBUTES ThreadSec = { 0 };
ProcessSec.lpSecurityDescriptor = NULL;
ProcessSec.nLength = sizeof(ProcessSec);
ProcessSec.bInheritHandle = TRUE;
ThreadSec.lpSecurityDescriptor = NULL;
ThreadSec.nLength = sizeof(ThreadSec);
ThreadSec.bInheritHandle = FALSE;
WCHAR Program[] = L"D:\test.exe";
cout << "
开始创建子进程
" << endl;
BOOL Process = CreateProcess((LPCWSTR)&Program, NULL , &ProcessSec, &ThreadSec,
TRUE, NULL, NULL, NULL, &StartUpInfo, &ProcessInformation
);
if (Process == 0) cout << "CreateProcess 错误代码: " << GetLastError() << endl;
return 0;
}
#include <Windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[])
{
if (OpenMutex(MUTEX_ALL_ACCESS, TRUE, TEXT("KernelObj-kb5j-bs36-55kv")))
cout << "内核对象已经被创建没有与之对应的内核对象" << endl;
else
cout << "没有与之对应的内核对象" << endl;
return 0;
}
0x03 获取进程 SessionId 和检测进程是否有副本
#include <Windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[])
{
DWORD ProcessId = GetCurrentProcessId();
DWORD SessionId = NULL;
if (ProcessIdToSessionId(ProcessId, &SessionId))
cout << " ProcessId: " << ProcessId << " - SessionId: " << SessionId << endl;
else
cout << "调用失败,错误代码: " << GetLastError() << endl;
return 0;
}
#include <Windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[])
{
HANDLE KernelObj = CreateMutex(NULL, FALSE, TEXT("KernelObj"));
if (GetLastError() == ERROR_ALREADY_EXISTS) {
cout << "进程已存在,新生成进程 ID: " << GetCurrentProcessId() << endl;
CloseHandle(KernelObj);
}
while (true)
Sleep(20);
return(0);
}
- 借助 Process Explore 工具也可以看出其创建过程
0x04 DuplicateHandle 获取当前进程的真实句柄
#include <Windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
int main(int argc, char *argv[])
{
HANDLE DupProcessHandle = NULL;
BOOL res = DuplicateHandle(
GetCurrentProcess(),
GetCurrentProcess(),
GetCurrentProcess(),
&DupProcessHandle,
0, FALSE, DUPLICATE_SAME_ACCESS
);
if (res)
{
cout << "[*] 当前进程的真实句柄为: " << DupProcessHandle << endl;
cout << "[*] 当前进程的伪造句柄为: " << GetCurrentProcess() << endl;
}
return(0);
}
- DuplicateHandle 在进行进程间复制时,若子进程需要使用复制的内核对象,仍然需要通过命令行或者 IPC 等将内核句柄值传递给子进程