最近在研究syscall相关的技术,无意中发现了这个NtSockets(只使用NtCreateFile和NtDeviceIoControlFile 函数,直接操作afd.sys驱动实现socket),感谢作者@x86matthew
原文链接 NTSockets - Downloading a file via HTTP using the NtCreateFile and NtDeviceIoControlFile syscalls
作者只实现了TCP-client的代码,并且x86下测试通过,但是在x64模式下连接到服务端时出现了错误。
根据函数的返回状态 0xc000000d 可知是参数错误。
根据代码
可以推测应该是传入的pData和dwLength出现了错误,根据调用关系
那么问题就出在结构体NTSockets_ConnectDataStruct上。
随便在网上找了个TCP-Client的代码,选择x64模式,在connect上下断点,当在connect断下来后,再在NtDeviceIoControlFile上下断点,再运行。
可以看到有几次触发断点
这里我们只关心 dwIoControlCode为0x012007 的调用。
通过对比参数可以找到参数以及大小。
而NtSockets代码参数是
重新定义下NTSockets_ConnectDataStruct结构体就可以了。
SIZE_T x86下是ULONG 在x64下是ULONGLONG。
根据代码可以看出TCP创建句柄跟bExtendedAttributes有关。所以我们关注下这个参数。
在socket函数下断点,断下来后在NtCreateFile函数下断点。堆栈情况如下
这是x64下的情况,去除前4个参数(利用寄存器传参),以上是第5-11参数。
这里我们只关注 后两个参数
对比NtSockets的EaBuffer
我解惑的数据和作者给出的有些出入,不过不影响使用。
直接将socket的参数调整成UDP的。还是在socket断下来以后,给NtCreateFile下断点,以下是udp的堆栈情况。
只要替换NtSockets中的bExtendedAttributes数组就可以产生UDP的连接。
vs完整工程见附件。
以上为UDP测试动画。
以上为TCP测试动画。
#未完待续
随后附上TCP-Server和UDP-Server的代码实现。敬请期待。。。
NtDeviceIoControlFile(pSocketData
-
>hSocket, pSocketData
-
>hStatusEvent, NULL, NULL, &IoStatusBlock, dwIoControlCode, (void
*
)pData, dwLength, bOutputBlock, sizeof(bOutputBlock));
NtDeviceIoControlFile(pSocketData
-
>hSocket, pSocketData
-
>hStatusEvent, NULL, NULL, &IoStatusBlock, dwIoControlCode, (void
*
)pData, dwLength, bOutputBlock, sizeof(bOutputBlock));
struct NTSockets_ConnectDataStruct NTSockets_ConnectData;
NTSockets_ConnectData.dwUnknown1
=
0
;
NTSockets_ConnectData.dwUnknown2
=
0
;
NTSockets_ConnectData.dwUnknown3
=
0
;
NTSockets_ConnectData.SockAddr.sin_family
=
AF_INET;
NTSockets_ConnectData.SockAddr.sin_addr.s_addr
=
dwConnectAddr;
NTSockets_ConnectData.SockAddr.sin_port
=
wConnectPort;
ULONG sz
=
sizeof(NTSockets_ConnectData);
if
(NTSockets_SocketDriverMsg(pSocketData,
0x00012007
, (BYTE
*
)&NTSockets_ConnectData, sz, NULL) !
=
0
)
{
/
/
error
return
1
;
}
struct NTSockets_ConnectDataStruct NTSockets_ConnectData;
NTSockets_ConnectData.dwUnknown1
=
0
;
NTSockets_ConnectData.dwUnknown2
=
0
;
NTSockets_ConnectData.dwUnknown3
=
0
;
NTSockets_ConnectData.SockAddr.sin_family
=
AF_INET;
NTSockets_ConnectData.SockAddr.sin_addr.s_addr
=
dwConnectAddr;
NTSockets_ConnectData.SockAddr.sin_port
=
wConnectPort;
ULONG sz
=
sizeof(NTSockets_ConnectData);
if
(NTSockets_SocketDriverMsg(pSocketData,
0x00012007
, (BYTE
*
)&NTSockets_ConnectData, sz, NULL) !
=
0
)
{
/
/
error
return
1
;
}
struct NTSockets_ConnectDataStruct
{
ULONG dwUnknown1;
ULONG dwUnknown2;
ULONG dwUnknown3;
struct sockaddr_in SockAddr;
};
struct NTSockets_ConnectDataStruct
{
ULONG dwUnknown1;
ULONG dwUnknown2;
ULONG dwUnknown3;
struct sockaddr_in SockAddr;
};
dwIoControlCode
0x01207b
mswsock.dll!SockGetInformation() Unknown
0x0120bf
mswsock.dll!WSPSetSockOpt() Unknown
0x012003
mswsock.dll!WSPBind() Unknown
0x012047
mswsock.dll!SockSetHandleContext() Unknown
0x012007
mswsock.dll!SockDoConnectReal() Unknown
dwIoControlCode
0x01207b
mswsock.dll!SockGetInformation() Unknown
0x0120bf
mswsock.dll!WSPSetSockOpt() Unknown
0x012003
mswsock.dll!WSPBind() Unknown
0x012047
mswsock.dll!SockSetHandleContext() Unknown
0x012007
mswsock.dll!SockDoConnectReal() Unknown
size
0x28
0x000000D8606FEE40
00
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
|AFIN |port |
-
-
-
IP
-
-
-
|
0x000000D8606FEE50
30
ef
6f
60
d8
00
00
00
02
00
00
50
7f
00
00
01
|
-
-
-
-
-
-
ZERO8
-
-
-
-
-
-
-
-
-
-
|
0x000000D8606FEE60
00
00
00
00
00
00
00
00
size
0x28
0x000000D8606FEE40
00
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
|AFIN |port |
-
-
-
IP
-
-
-
|
0x000000D8606FEE50
30
ef
6f
60
d8
00
00
00
02
00
00
50
7f
00
00
01
|
-
-
-
-
-
-
ZERO8
-
-
-
-
-
-
-
-
-
-
|
0x000000D8606FEE60
00
00
00
00
00
00
00
00
size
0x1c
|AFIN |port
0x0000002EE86FD9F8
00
00
00
00
00
00
00
00
00
00
00
00
02
00
00
50
|
-
-
-
IP
-
-
-
| |
-
-
-
-
-
-
ZERO8
-
-
-
-
-
-
-
-
-
-
|
0x0000002EE86FDA08
c0 a8
0a
75
00
00
00
00
00
00
00
00
size
0x1c
|AFIN |port
0x0000002EE86FD9F8
00
00
00
00
00
00
00
00
00
00
00
00
02
00
00
50
|
-
-
-
IP
-
-
-
| |
-
-
-
-
-
-
ZERO8
-
-
-
-
-
-
-
-
-
-
|
0x0000002EE86FDA08
c0 a8
0a
75
00
00
00
00
00
00
00
00
struct NTSockets_ConnectDataStruct
{
SIZE_T dwUnknown1;
SIZE_T dwUnknown2;
SIZE_T dwUnknown3;
struct sockaddr_in SockAddr;
};
struct NTSockets_ConnectDataStruct
{
SIZE_T dwUnknown1;
SIZE_T dwUnknown2;
SIZE_T dwUnknown3;
struct sockaddr_in SockAddr;
};
NTSTATUS NTAPI NtCreateFile ( PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
PLARGE_INTEGER AllocateSize,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer,
ULONG EaLength
)
dwStatus
=
NtCreateFile(&hSocket,
0xC0140000
, &ObjectAttributes, &IoStatusBlock, NULL,
0
, FILE_SHARE_READ | FILE_SHARE_WRITE,
1
,
0
, &bExtendedAttributes, sizeof(bExtendedAttributes));
NTSTATUS NTAPI NtCreateFile ( PHANDLE FileHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes,
PIO_STATUS_BLOCK IoStatusBlock,
PLARGE_INTEGER AllocateSize,
ULONG FileAttributes,
ULONG ShareAccess,
ULONG CreateDisposition,
ULONG CreateOptions,
PVOID EaBuffer,
ULONG EaLength
)
dwStatus
=
NtCreateFile(&hSocket,
0xC0140000
, &ObjectAttributes, &IoStatusBlock, NULL,
0
, FILE_SHARE_READ | FILE_SHARE_WRITE,
1
,
0
, &bExtendedAttributes, sizeof(bExtendedAttributes));
0x000000EC37FCEE40
0000000000000000
........
0x000000EC37FCEE48
004f004400000000
....D.O.
0x000000EC37FCEE50
000000ec00000003
....ì...
0x000000EC37FCEE58
000000ec00000003
....ì...
0x000000EC37FCEE60
000000ec00000000
....ì...
0x000000EC37FCEE68
000000ec37fcef60
`ïü
7
ì...
0x000000EC37FCEE70
002e006b00000039
9.
..k...
0x000000EC37FCEE40
0000000000000000
........
0x000000EC37FCEE48
004f004400000000
....D.O.
0x000000EC37FCEE50
000000ec00000003
....ì...
0x000000EC37FCEE58
000000ec00000003
....ì...
0x000000EC37FCEE60
000000ec00000000
....ì...
0x000000EC37FCEE68
000000ec37fcef60
`ïü
7
ì...
0x000000EC37FCEE70
002e006b00000039
9.
..k...
0x000000EC37FCEE68
000000ec37fcef60
`ïü
7
ì... EaBuffer
0x000000EC37FCEE70
002e006b00000039
9.
..k... EaLength
EaBuffer:
0x000000EC37FCEF60
00
00
00
00
00
0f
1e
00
41
66
64
4f
70
65
6e
50
........AfdOpenP
0x000000EC37FCEF70
61
63
6b
65
74
58
58
00
00
00
00
00
00
00
00
00
acketXX.........
0x000000EC37FCEF80
02
00
00
00
01
00
00
00
06
00
00
00
00
00
00
00
................
0x000000EC37FCEF90
08
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
................
0x000000EC37FCEE68
000000ec37fcef60
`ïü
7
ì... EaBuffer
0x000000EC37FCEE70
002e006b00000039
9.
..k... EaLength
EaBuffer:
0x000000EC37FCEF60
00
00
00
00
00
0f
1e
00
41
66
64
4f
70
65
6e
50
........AfdOpenP
0x000000EC37FCEF70
61
63
6b
65
74
58
58
00
00
00
00
00
00
00
00
00
acketXX.........
0x000000EC37FCEF80
02
00
00
00
01
00
00
00
06
00
00
00
00
00
00
00
................
0x000000EC37FCEF90
08
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
................
BYTE bExtendedAttributes[]
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x0F
,
0x1E
,
0x00
,
0x41
,
0x66
,
0x64
,
0x4F
,
0x70
,
0x65
,
0x6E
,
0x50
,
0x61
,
0x63
,
0x6B
,
0x65
,
0x74
,
0x58
,
0x58
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x06
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x60
,
0xEF
,
0x3D
,
0x47
,
0xFE
};
BYTE bExtendedAttributes[]
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x0F
,
0x1E
,
0x00
,
0x41
,
0x66
,
0x64
,
0x4F
,
0x70
,
0x65
,
0x6E
,
0x50
,
0x61
,
0x63
,
0x6B
,
0x65
,
0x74
,
0x58
,
0x58
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x06
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x60
,
0xEF
,
0x3D
,
0x47
,
0xFE
};
0x000000B698EFF308
0000000000000000
........
0x000000B698EFF310
0000000000000000
........
0x000000B698EFF318
004f004400000000
....D.O.
0x000000B698EFF320
000000b600000003
....¶...
0x000000B698EFF328
000000b600000003
....¶...
0x000000B698EFF330
000000b600000000
....¶...
0x000000B698EFF338
000000b698eff430
0
ô...
0x000000B698EFF340
002e006b00000039
9.
..k...
EaBuffer:
0x000000B698EFF430
00
00
00
00
00
0f
1e
00
41
66
64
4f
70
65
6e
50
........AfdOpenP
0x000000B698EFF440
61
63
6b
65
74
58
58
00
11
00
00
00
00
00
00
00
acketXX.........
0x000000B698EFF450
02
00
00
00
02
00
00
00
11
00
00
00
00
00
00
00
................
0x000000B698EFF460
08
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
................
0x000000B698EFF308
0000000000000000
........
0x000000B698EFF310
0000000000000000
........
0x000000B698EFF318
004f004400000000
....D.O.
0x000000B698EFF320
000000b600000003
....¶...
0x000000B698EFF328
000000b600000003
....¶...
0x000000B698EFF330
000000b600000000
....¶...
0x000000B698EFF338
000000b698eff430
0
ô...
0x000000B698EFF340
002e006b00000039
9.
..k...
EaBuffer:
0x000000B698EFF430
00
00
00
00
00
0f
1e
00
41
66
64
4f
70
65
6e
50
........AfdOpenP
0x000000B698EFF440
61
63
6b
65
74
58
58
00
11
00
00
00
00
00
00
00
acketXX.........
0x000000B698EFF450
02
00
00
00
02
00
00
00
11
00
00
00
00
00
00
00
................
0x000000B698EFF460
08
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
................
struct IO_STATUS_BLOCK
{
union
{
DWORD Status;
PVOID Pointer;
};
DWORD
*
Information;
};
struct UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR
Buffer
;
};
struct OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
struct UNICODE_STRING
*
ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
};
struct FILE_FULL_EA_INFORMATION
{
ULONG NextEntryOffset;
UCHAR Flags;
UCHAR EaNameLength;
USHORT EaValueLength;
CHAR EaName[
1
];
};
struct NTSockets_ConnectDataStruct
{
SIZE_T dwUnknown1;
SIZE_T dwUnknown2;
SIZE_T dwUnknown3;
struct sockaddr_in SockAddr;
};
struct NTSockets_BindDataStruct
{
DWORD dwUnknown1;
struct sockaddr_in SockAddr;
};
struct NTSockets_DataBufferStruct
{
DWORD dwDataLength;
BYTE
*
pData;
};
struct NTSockets_SendRecvDataStruct
{
struct NTSockets_DataBufferStruct
*
pBufferList;
DWORD dwBufferCount;
DWORD dwUnknown1;
DWORD dwUnknown2;
};
struct NTSockets_SocketDataStruct
{
HANDLE hSocket;
HANDLE hStatusEvent;
};
struct DNSClient_HeaderStruct
{
WORD wTransID;
WORD wFlags;
WORD wQuestionCount;
WORD wAnswerRecordCount;
WORD wAuthorityRecordCount;
WORD wAdditionalRecordCount;
};
struct DNSClient_RequestQueryDetailsStruct
{
WORD wType;
WORD wClass;
};
struct DNSClient_ResponseAnswerHeaderStruct
{
WORD wName;
WORD wType;
WORD wClass;
WORD wTTL[
2
];
WORD wLength;
};
DWORD(NTAPI
*
NtDeviceIoControlFile)(HANDLE FileHandle, HANDLE Event, VOID
*
ApcRoutine, PVOID ApcContext, struct IO_STATUS_BLOCK
*
IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength);
DWORD(NTAPI
*
NtCreateFile)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, struct OBJECT_ATTRIBUTES
*
ObjectAttributes, struct IO_STATUS_BLOCK
*
IoStatusBlock, LARGE_INTEGER
*
AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
DWORD NTSockets_CreateTcpSocket(struct NTSockets_SocketDataStruct
*
pSocketData,
int
bTcp)
{
struct IO_STATUS_BLOCK IoStatusBlock;
HANDLE hEvent
=
NULL;
HANDLE hSocket
=
NULL;
struct OBJECT_ATTRIBUTES ObjectAttributes;
struct NTSockets_SocketDataStruct SocketData;
struct UNICODE_STRING ObjectFilePath;
DWORD dwStatus
=
0
;
/
*
tcp extended attr
0x0000003395EFF130
00
00
00
00
00
0f
1e
00
41
66
64
4f
70
65
6e
50
........AfdOpenP
0x0000003395EFF140
61
63
6b
65
74
58
58
00
00
00
00
00
00
00
00
00
acketXX.........
0x0000003395EFF150
02
00
00
00
01
00
00
00
06
00
00
00
00
00
00
00
................
0x0000003395EFF160
08
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
................
*
/
/
*
udp
0x000000506EF3F040
00
00
00
00
00
0f
1e
00
41
66
64
4f
70
65
6e
50
........AfdOpenP
0x000000506EF3F050
61
63
6b
65
74
58
58
00
11
00
00
00
00
00
00
00
acketXX.........
0x000000506EF3F060
02
00
00
00
02
00
00
00
11
00
00
00
00
00
00
00
................
0x000000506EF3F070
08
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
................
*
/
BYTE bEaUdp[]
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x0f
,
0x1e
,
0x00
,
0x41
,
0x66
,
0x64
,
0x4f
,
0x70
,
0x65
,
0x6e
,
0x50
,
0x61
,
0x63
,
0x6b
,
0x65
,
0x74
,
0x58
,
0x58
,
0x00
,
0x11
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x11
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x08
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
BYTE bExtendedAttributes[]
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x0F
,
0x1E
,
0x00
,
0x41
,
0x66
,
0x64
,
0x4F
,
0x70
,
0x65
,
0x6E
,
0x50
,
0x61
,
0x63
,
0x6B
,
0x65
,
0x74
,
0x58
,
0x58
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x06
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x60
,
0xEF
,
0x3D
,
0x47
,
0xFE
};
printf(
"[*] NTSockets_CreateTcpSocket:: is %s !\n"
,bTcp ?
"TCP"
:
"UDP"
);
struct FILE_FULL_EA_INFORMATION
*
ffe;
ffe
=
(struct FILE_FULL_EA_INFORMATION
*
)bTcp ? bExtendedAttributes : bEaUdp;
/
/
create status event
hEvent
=
CreateEvent(NULL,
0
,
0
, NULL);
if
(hEvent
=
=
NULL)
{
/
/
error
return
1
;
}
/
/
set
afd endpoint path
memset((void
*
)&ObjectFilePath,
0
, sizeof(ObjectFilePath));
ObjectFilePath.
Buffer
=
L
"\\Device\\Afd\\Endpoint"
;
ObjectFilePath.Length
=
wcslen(ObjectFilePath.
Buffer
)
*
sizeof(wchar_t);
ObjectFilePath.MaximumLength
=
ObjectFilePath.Length;
/
/
initialise
object
attributes
memset((void
*
)&ObjectAttributes,
0
, sizeof(ObjectAttributes));
ObjectAttributes.Length
=
sizeof(ObjectAttributes);
ObjectAttributes.ObjectName
=
&ObjectFilePath;
ObjectAttributes.Attributes
=
0x40
;
/
/
create socket handle
IoStatusBlock.Status
=
0
;
IoStatusBlock.Information
=
NULL;
dwStatus
=
NtCreateFile(&hSocket,
0xC0140000
, &ObjectAttributes, &IoStatusBlock, NULL,
0
, FILE_SHARE_READ | FILE_SHARE_WRITE,
1
,
0
, ffe, sizeof(bExtendedAttributes));
if
(dwStatus !
=
0
)
{
/
/
error
CloseHandle(hEvent);
return
1
;
}
/
/
initialise SocketData
object
memset((void
*
)&SocketData,
0
, sizeof(SocketData));
SocketData.hSocket
=
hSocket;
SocketData.hStatusEvent
=
hEvent;
/
/
store socket data
memcpy((void
*
)pSocketData, (void
*
)&SocketData, sizeof(SocketData));
return
0
;
}
DWORD NTSockets_SocketDriverMsg(struct NTSockets_SocketDataStruct
*
pSocketData, DWORD dwIoControlCode, BYTE
*
pData, DWORD dwLength, DWORD
*
pdwOutputInformation)
{
struct IO_STATUS_BLOCK IoStatusBlock;
DWORD dwStatus
=
0
;
BYTE bOutputBlock[
0x10
];
/
/
reset status event
ResetEvent(pSocketData
-
>hStatusEvent);
/
/
send device control request
IoStatusBlock.Status
=
0
;
IoStatusBlock.Information
=
NULL;
dwStatus
=
NtDeviceIoControlFile(pSocketData
-
>hSocket, pSocketData
-
>hStatusEvent, NULL, NULL, &IoStatusBlock, dwIoControlCode, (void
*
)pData, dwLength, bOutputBlock, sizeof(bOutputBlock));
if
(dwStatus
=
=
STATUS_PENDING)
{
/
/
response pending
-
wait
for
event
if
(WaitForSingleObject(pSocketData
-
>hStatusEvent,
-
1
) !
=
WAIT_OBJECT_0)
{
/
/
error
return
1
;
}
/
/
complete
-
get final status code
dwStatus
=
IoStatusBlock.Status;
}
/
/
check
for
errors
if
(dwStatus !
=
0
)
{
/
/
error
return
1
;
}
if
(pdwOutputInformation !
=
NULL)
{
/
/
store output info
*
pdwOutputInformation
=
(DWORD)IoStatusBlock.Information;
}
return
0
;
}
DWORD NTSockets_ConvertIP(char
*
pIP, DWORD
*
pdwAddr)
{
char szCurrOctet[
8
];
DWORD dwCurrOctetIndex
=
0
;
DWORD dwCompletedOctetCount
=
0
;
char
*
pCurrByte
=
NULL;
DWORD dwEndOfOctet
=
0
;
DWORD dwEndOfString
=
0
;
DWORD dwOctet
=
0
;
BYTE bOctets[
4
];
DWORD dwAddr
=
0
;
/
/
read IP string
memset(szCurrOctet,
0
, sizeof(szCurrOctet));
dwCurrOctetIndex
=
0
;
pCurrByte
=
pIP;
for
(;;)
{
/
/
process current character
dwEndOfOctet
=
0
;
if
(
*
pCurrByte
=
=
'\0'
)
{
/
/
end of string
dwEndOfOctet
=
1
;
dwEndOfString
=
1
;
}
else
if
(
*
pCurrByte
=
=
'.'
)
{
/
/
end of octet
dwEndOfOctet
=
1
;
}
else
{
/
/
ensure this character
is
a number
if
(
*
pCurrByte >
=
'0'
&&
*
pCurrByte <
=
'9'
)
{
if
(dwCurrOctetIndex >
2
)
{
/
/
invalid ip
return
1
;
}
/
/
store current character
szCurrOctet[dwCurrOctetIndex]
=
*
pCurrByte;
dwCurrOctetIndex
+
+
;
}
else
{
/
/
invalid ip
return
1
;
}
}
/
/
check
if
the current octet
is
complete
if
(dwEndOfOctet !
=
0
)
{
if
(dwCurrOctetIndex
=
=
0
)
{
/
/
invalid ip
return
1
;
}
/
/
convert octet string to integer
dwOctet
=
atoi(szCurrOctet);
if
(dwOctet >
255
)
{
/
/
invalid ip
return
1
;
}
/
/
already read
4
octets
if
(dwCompletedOctetCount >
=
4
)
{
/
/
invalid ip
return
1
;
}
/
/
store current octet
bOctets[dwCompletedOctetCount]
=
(BYTE)dwOctet;
/
/
current octet complete
dwCompletedOctetCount
+
+
;
if
(dwEndOfString !
=
0
)
{
/
/
end of string
break
;
}
/
/
reset szCurrOctet string
memset(szCurrOctet,
0
, sizeof(szCurrOctet));
dwCurrOctetIndex
=
0
;
}
/
/
move to the
next
character
pCurrByte
+
+
;
}
/
/
ensure
4
octets were found
if
(dwCompletedOctetCount !
=
4
)
{
/
/
invalid string
return
1
;
}
/
/
store octets
in
dword value
memcpy((void
*
)&dwAddr, bOctets,
4
);
/
/
store value
*
pdwAddr
=
dwAddr;
return
0
;
}
WORD NTSockets_Swap16BitByteOrder(WORD wValue)
{
WORD wNewValue
=
0
;
/
/
swap byte order
-
this assumes we are running on an x86
-
based chip
/
/
*
(BYTE
*
)((DWORD)&wNewValue
+
0
)
=
*
(BYTE
*
)((DWORD)&wValue
+
1
);
/
/
*
(BYTE
*
)((DWORD)&wNewValue
+
1
)
=
*
(BYTE
*
)((DWORD)&wValue
+
0
);
*
(((BYTE
*
)&wNewValue)
+
0
)
=
*
(((BYTE
*
)&wValue)
+
1
);
*
(((BYTE
*
)&wNewValue)
+
1
)
=
*
(((BYTE
*
)&wValue)
+
0
);
return
wNewValue;
}
DWORD NTSockets_Connect(struct NTSockets_SocketDataStruct
*
pSocketData, char
*
pIP, WORD wPort)
{
struct NTSockets_BindDataStruct NTSockets_BindData;
struct NTSockets_ConnectDataStruct NTSockets_ConnectData;
WORD wConnectPort
=
0
;
DWORD dwConnectAddr
=
0
;
/
/
bind to local port
memset((void
*
)&NTSockets_BindData,
0
, sizeof(NTSockets_BindData));
NTSockets_BindData.dwUnknown1
=
2
;
NTSockets_BindData.SockAddr.sin_family
=
AF_INET;
NTSockets_BindData.SockAddr.sin_addr.s_addr
=
INADDR_ANY;
NTSockets_BindData.SockAddr.sin_port
=
0
;
if
(NTSockets_SocketDriverMsg(pSocketData,
0x00012003
, (BYTE
*
)&NTSockets_BindData, sizeof(NTSockets_BindData), NULL) !
=
0
)
{
/
/
error
return
1
;
}
/
/
read connection ip
if
(NTSockets_ConvertIP(pIP, &dwConnectAddr) !
=
0
)
{
/
/
error
return
1
;
}
/
/
use network byte order
for
connection port
/
/
wConnectPort
=
htons(wPort);
wConnectPort
=
NTSockets_Swap16BitByteOrder(wPort);
/
/
connect to remote port
memset((void
*
)&NTSockets_ConnectData,
0
, sizeof(NTSockets_ConnectData));
NTSockets_ConnectData.dwUnknown1
=
0
;
NTSockets_ConnectData.dwUnknown2
=
0
;
NTSockets_ConnectData.dwUnknown3
=
0
;
NTSockets_ConnectData.SockAddr.sin_family
=
AF_INET;
NTSockets_ConnectData.SockAddr.sin_addr.s_addr
=
dwConnectAddr;
NTSockets_ConnectData.SockAddr.sin_port
=
wConnectPort;
ULONG sz
=
sizeof(NTSockets_ConnectData);
if
(NTSockets_SocketDriverMsg(pSocketData,
0x00012007
, (BYTE
*
)&NTSockets_ConnectData, sz, NULL) !
=
0
)
{
/
/
error
return
1
;
}
return
0
;
}
DWORD NTSockets_Send(struct NTSockets_SocketDataStruct
*
pSocketData, BYTE
*
pData, DWORD dwLength)
{
struct NTSockets_SendRecvDataStruct NTSockets_SendRecvData;
struct NTSockets_DataBufferStruct NTSockets_DataBuffer;
DWORD dwBytesSent
=
0
;
BYTE
*
pCurrSendPtr
=
NULL;
DWORD dwBytesRemaining
=
0
;
/
/
set
initial values
pCurrSendPtr
=
pData;
dwBytesRemaining
=
dwLength;
/
/
send data
for
(;;)
{
if
(dwBytesRemaining
=
=
0
)
{
/
/
finished
break
;
}
/
/
set
data
buffer
values
memset((void
*
)&NTSockets_DataBuffer,
0
, sizeof(NTSockets_DataBuffer));
NTSockets_DataBuffer.dwDataLength
=
dwBytesRemaining;
NTSockets_DataBuffer.pData
=
pCurrSendPtr;
/
/
send current block
memset((void
*
)&NTSockets_SendRecvData,
0
, sizeof(NTSockets_SendRecvData));
NTSockets_SendRecvData.pBufferList
=
&NTSockets_DataBuffer;
NTSockets_SendRecvData.dwBufferCount
=
1
;
NTSockets_SendRecvData.dwUnknown1
=
0
;
NTSockets_SendRecvData.dwUnknown2
=
0
;
if
(NTSockets_SocketDriverMsg(pSocketData,
0x0001201F
, (BYTE
*
)&NTSockets_SendRecvData, sizeof(NTSockets_SendRecvData), &dwBytesSent) !
=
0
)
{
/
/
error
return
1
;
}
if
(dwBytesSent
=
=
0
)
{
/
/
socket disconnected
return
1
;
}
/
/
update values
pCurrSendPtr
+
=
dwBytesSent;
dwBytesRemaining
-
=
dwBytesSent;
}
return
0
;
}
int
NTSockets_Recv(struct NTSockets_SocketDataStruct
*
pSocketData, BYTE
*
pData, DWORD dwLength)
{
struct NTSockets_SendRecvDataStruct NTSockets_SendRecvData;
struct NTSockets_DataBufferStruct NTSockets_DataBuffer;
DWORD dwBytesReceived
=
0
;
/
/
set
data
buffer
values
memset((void
*
)&NTSockets_DataBuffer,
0
, sizeof(NTSockets_DataBuffer));
NTSockets_DataBuffer.dwDataLength
=
dwLength;
NTSockets_DataBuffer.pData
=
pData;
/
/
recv current block
memset((void
*
)&NTSockets_SendRecvData,
0
, sizeof(NTSockets_SendRecvData));
NTSockets_SendRecvData.pBufferList
=
&NTSockets_DataBuffer;
NTSockets_SendRecvData.dwBufferCount
=
1
;
NTSockets_SendRecvData.dwUnknown1
=
0
;
NTSockets_SendRecvData.dwUnknown2
=
0x20
;
if
(NTSockets_SocketDriverMsg(pSocketData,
0x00012017
, (BYTE
*
)&NTSockets_SendRecvData, sizeof(NTSockets_SendRecvData), &dwBytesReceived) !
=
0
)
{
/
/
error
return
-
1
;
}
return
dwBytesReceived;
}
DWORD NTSockets_CloseSocket(struct NTSockets_SocketDataStruct
*
pSocketData)
{
/
/
close handles
CloseHandle(pSocketData
-
>hSocket);
CloseHandle(pSocketData
-
>hStatusEvent);
return
0
;
}
DWORD DNSClient_Query(char
*
pDNSClient_IP, char
*
pTargetHost, char
*
pOutput, DWORD dwOutputMaxLength)
{
struct NTSockets_SocketDataStruct SocketData;
struct DNSClient_HeaderStruct DNSClient_RequestHeader;
struct DNSClient_RequestQueryDetailsStruct DNSClient_RequestQueryDetails;
struct DNSClient_HeaderStruct
*
pDNSClient_ResponseHeader
=
NULL;
struct DNSClient_ResponseAnswerHeaderStruct
*
pDNSClient_ResponseAnswerHeader
=
NULL;
DWORD dwIpAddrIndex
=
0
;
DWORD dwFoundRecord
=
0
;
DWORD dwCurrAnswerEntryStartIndex
=
0
;
DWORD dwHostLength
=
0
;
DWORD dwCurrLabelLength
=
0
;
WORD wRequestLength
=
0
;
WORD wResponseLength
=
0
;
WORD wBlockLength
=
0
;
WORD wAnswerCount
=
0
;
BYTE bIP[
4
];
BYTE bResponseBuffer[
4096
];
char szConvertedHost[
1024
];
char
*
pCurrDot
=
NULL;
char szIP[
32
];
/
/
convert target host name to dns
format
memset(szConvertedHost,
0
, sizeof(szConvertedHost));
_snprintf_s(szConvertedHost, sizeof(szConvertedHost)
-
1
,
-
1
,
".%s"
, pTargetHost);
dwHostLength
=
strlen(szConvertedHost)
+
1
;
for
(DWORD i
=
0
; i < dwHostLength; i
+
+
)
{
/
/
process domain labels
if
(szConvertedHost[i]
=
=
'.'
|| szConvertedHost[i]
=
=
'\0'
)
{
/
/
check
if
a previous separator exists
if
(pCurrDot !
=
NULL)
{
/
/
calculate current label length
dwCurrLabelLength
=
(DWORD)(&szConvertedHost[i]
-
pCurrDot);
dwCurrLabelLength
-
-
;
if
(dwCurrLabelLength
=
=
0
|| dwCurrLabelLength >
=
64
)
{
return
1
;
}
/
/
insert label length
*
pCurrDot
=
(char)dwCurrLabelLength;
}
/
/
store current dot position
pCurrDot
=
&szConvertedHost[i];
}
}
/
/
create socket handle
if
(NTSockets_CreateTcpSocket(&SocketData,
1
) !
=
0
)
{
/
/
error
return
1
;
}
/
/
connect to DNS server
if
(NTSockets_Connect(&SocketData, pDNSClient_IP,
53
) !
=
0
)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
calculate request length
wRequestLength
=
sizeof(struct DNSClient_HeaderStruct)
+
dwHostLength
+
sizeof(DNSClient_RequestQueryDetails);
wBlockLength
=
NTSockets_Swap16BitByteOrder(wRequestLength);
/
/
set
request header details
memset((void
*
)&DNSClient_RequestHeader,
0
, sizeof(DNSClient_RequestHeader));
DNSClient_RequestHeader.wTransID
=
NTSockets_Swap16BitByteOrder(
1
);
DNSClient_RequestHeader.wFlags
=
NTSockets_Swap16BitByteOrder(
0x100
);
DNSClient_RequestHeader.wQuestionCount
=
NTSockets_Swap16BitByteOrder(
1
);
/
/
type
A dns request
memset((void
*
)&DNSClient_RequestQueryDetails,
0
, sizeof(DNSClient_RequestQueryDetails));
DNSClient_RequestQueryDetails.wType
=
NTSockets_Swap16BitByteOrder(
1
);
DNSClient_RequestQueryDetails.wClass
=
NTSockets_Swap16BitByteOrder(
1
);
/
/
send request length
if
(NTSockets_Send(&SocketData, (BYTE
*
)&wBlockLength, sizeof(WORD)) !
=
0
)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
send request header
if
(NTSockets_Send(&SocketData, (BYTE
*
)&DNSClient_RequestHeader, sizeof(DNSClient_RequestHeader)) !
=
0
)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
send host name
if
(NTSockets_Send(&SocketData, (BYTE
*
)szConvertedHost, dwHostLength) !
=
0
)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
send host query details
if
(NTSockets_Send(&SocketData, (BYTE
*
)&DNSClient_RequestQueryDetails, sizeof(DNSClient_RequestQueryDetails)) !
=
0
)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
receive response length
if
(NTSockets_Recv(&SocketData, (BYTE
*
)&wBlockLength, sizeof(WORD)) !
=
0
)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
swap byte order
wResponseLength
=
NTSockets_Swap16BitByteOrder(wBlockLength);
/
/
validate response length
if
(wResponseLength < sizeof(struct DNSClient_HeaderStruct) || wResponseLength > sizeof(bResponseBuffer))
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
receive response data
memset((void
*
)bResponseBuffer,
0
, sizeof(bResponseBuffer));
if
(NTSockets_Recv(&SocketData, bResponseBuffer, wResponseLength) !
=
0
)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
set
response header ptr
pDNSClient_ResponseHeader
=
(struct DNSClient_HeaderStruct
*
)bResponseBuffer;
/
/
check flags (expect response, no error)
if
(pDNSClient_ResponseHeader
-
>wFlags !
=
NTSockets_Swap16BitByteOrder(
0x8180
))
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
validate question count
if
(pDNSClient_ResponseHeader
-
>wQuestionCount !
=
NTSockets_Swap16BitByteOrder(
1
))
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
get response answer count
wAnswerCount
=
NTSockets_Swap16BitByteOrder(pDNSClient_ResponseHeader
-
>wAnswerRecordCount);
/
/
read DNS response answers
dwCurrAnswerEntryStartIndex
=
wRequestLength;
for
(DWORD i
=
0
; i < (DWORD)wAnswerCount; i
+
+
)
{
/
/
validate start index
if
((dwCurrAnswerEntryStartIndex
+
sizeof(struct DNSClient_ResponseAnswerHeaderStruct)) > (DWORD)wResponseLength)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
get current response answer header ptr
pDNSClient_ResponseAnswerHeader
=
(struct DNSClient_ResponseAnswerHeaderStruct
*
)&bResponseBuffer[dwCurrAnswerEntryStartIndex];
/
/
check
if
this
is
a
type
A record
if
(pDNSClient_ResponseAnswerHeader
-
>wType
=
=
NTSockets_Swap16BitByteOrder(
1
) && pDNSClient_ResponseAnswerHeader
-
>wClass
=
=
NTSockets_Swap16BitByteOrder(
1
))
{
/
/
ensure value length
is
4
(ipv4 addr)
if
(pDNSClient_ResponseAnswerHeader
-
>wLength !
=
NTSockets_Swap16BitByteOrder(
4
))
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
validate ip addr index
dwIpAddrIndex
=
dwCurrAnswerEntryStartIndex
+
sizeof(struct DNSClient_ResponseAnswerHeaderStruct);
if
((dwIpAddrIndex
+
4
) > (DWORD)wResponseLength)
{
/
/
error
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
store IP addr
memcpy((void
*
)bIP, (void
*
)&bResponseBuffer[dwIpAddrIndex],
4
);
/
/
set
flag
dwFoundRecord
=
1
;
break
;
}
else
{
/
/
check
next
entry
dwCurrAnswerEntryStartIndex
+
=
sizeof(struct DNSClient_ResponseAnswerHeaderStruct);
dwCurrAnswerEntryStartIndex
+
=
NTSockets_Swap16BitByteOrder(pDNSClient_ResponseAnswerHeader
-
>wLength);
}
}
/
/
close socket
NTSockets_CloseSocket(&SocketData);
/
/
ensure a valid record was found
if
(dwFoundRecord
=
=
0
)
{
return
1
;
}
/
/
generate IP string
memset(szIP,
0
, sizeof(szIP));
_snprintf_s(szIP, sizeof(szIP)
-
1
,
-
1
,
"%u.%u.%u.%u"
, bIP[
0
], bIP[
1
], bIP[
2
], bIP[
3
]);
/
/
store value
strncpy_s(pOutput,
32
, szIP, dwOutputMaxLength);
return
0
;
}
int
main(
int
argc, char
*
argv[])
{
char
*
szIP
=
"127.0.0.1"
;
unsigned
int
dwPort
=
80
;
char
buffer
[
1024
]
=
"hello pediy.com !"
;
struct NTSockets_SocketDataStruct SocketData;
/
/
get NtDeviceIoControlFile function ptr
NtDeviceIoControlFile
=
(unsigned
long
(__stdcall
*
)(void
*
, void
*
, void
*
, void
*
, struct IO_STATUS_BLOCK
*
, unsigned
long
, void
*
, unsigned
long
, void
*
, unsigned
long
))GetProcAddress(GetModuleHandle(L
"ntdll.dll"
),
"NtDeviceIoControlFile"
);
if
(NtDeviceIoControlFile
=
=
NULL)
{
return
1
;
}
/
/
get NtCreateFile function ptr
NtCreateFile
=
(unsigned
long
(__stdcall
*
)(void
*
*
, unsigned
long
, struct OBJECT_ATTRIBUTES
*
, struct IO_STATUS_BLOCK
*
, union _LARGE_INTEGER
*
, unsigned
long
, unsigned
long
, unsigned
long
, unsigned
long
, void
*
, unsigned
long
))GetProcAddress(GetModuleHandle(L
"ntdll.dll"
),
"NtCreateFile"
);
if
(NtCreateFile
=
=
NULL)
{
return
1
;
}
/
/
create socket handle
printf(
"create socket !\n"
);
if
(NTSockets_CreateTcpSocket(&SocketData,
1
) !
=
0
)
{
/
/
error
printf(
"Error: Failed to create TCP socket\n"
);
return
1
;
}
/
/
connect to server
printf(
"connect to server !\n"
);
if
(NTSockets_Connect(&SocketData, szIP, (WORD)dwPort) !
=
0
)
{
/
/
error
printf(
"Error: Failed to connect to server\n"
);
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
send
printf(
"send ... !\n"
);
if
(NTSockets_Send(&SocketData, (BYTE
*
)
buffer
, strlen(
buffer
)) !
=
0
)
{
/
/
error
printf(
"Error: Failed to send data to server\n"
);
NTSockets_CloseSocket(&SocketData);
return
1
;
}
/
/
recv
printf(
"recv ... !\n"
);
memset(
buffer
,
0
, sizeof(
buffer
));
if
(NTSockets_Recv(&SocketData, (BYTE
*
)
buffer
, sizeof(
buffer
) ) <
0
)
{
/
/
error
printf(
"Error: Failed to read HTTP response header\n"
);
NTSockets_CloseSocket(&SocketData);
return
1
;
}
printf(
"buffer is: %s \n"
,
buffer
);
printf(
"close socket !\n"
);
NTSockets_CloseSocket(&SocketData);
getchar();
return
0
;
}
struct IO_STATUS_BLOCK
{
union
{
DWORD Status;
PVOID Pointer;
};
DWORD
*
Information;
};
struct UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR
Buffer
;
};
struct OBJECT_ATTRIBUTES
{
ULONG Length;
HANDLE RootDirectory;
struct UNICODE_STRING
*
ObjectName;
ULONG Attributes;
PVOID SecurityDescriptor;
PVOID SecurityQualityOfService;
};
struct FILE_FULL_EA_INFORMATION
{
ULONG NextEntryOffset;
UCHAR Flags;
UCHAR EaNameLength;
USHORT EaValueLength;
CHAR EaName[
1
];
};
struct NTSockets_ConnectDataStruct
{
SIZE_T dwUnknown1;
SIZE_T dwUnknown2;
SIZE_T dwUnknown3;
struct sockaddr_in SockAddr;
};
struct NTSockets_BindDataStruct
{
DWORD dwUnknown1;
struct sockaddr_in SockAddr;
};
struct NTSockets_DataBufferStruct
{
DWORD dwDataLength;
BYTE
*
pData;
};
struct NTSockets_SendRecvDataStruct
{
struct NTSockets_DataBufferStruct
*
pBufferList;
DWORD dwBufferCount;
DWORD dwUnknown1;
DWORD dwUnknown2;
};
struct NTSockets_SocketDataStruct
{
HANDLE hSocket;
HANDLE hStatusEvent;
};
struct DNSClient_HeaderStruct
{
WORD wTransID;
WORD wFlags;
WORD wQuestionCount;
WORD wAnswerRecordCount;
WORD wAuthorityRecordCount;
WORD wAdditionalRecordCount;
};
struct DNSClient_RequestQueryDetailsStruct
{
WORD wType;
WORD wClass;
};
struct DNSClient_ResponseAnswerHeaderStruct
{
WORD wName;
WORD wType;
WORD wClass;
WORD wTTL[
2
];
WORD wLength;
};
DWORD(NTAPI
*
NtDeviceIoControlFile)(HANDLE FileHandle, HANDLE Event, VOID
*
ApcRoutine, PVOID ApcContext, struct IO_STATUS_BLOCK
*
IoStatusBlock, ULONG IoControlCode, PVOID InputBuffer, ULONG InputBufferLength, PVOID OutputBuffer, ULONG OutputBufferLength);
DWORD(NTAPI
*
NtCreateFile)(PHANDLE FileHandle, ACCESS_MASK DesiredAccess, struct OBJECT_ATTRIBUTES
*
ObjectAttributes, struct IO_STATUS_BLOCK
*
IoStatusBlock, LARGE_INTEGER
*
AllocationSize, ULONG FileAttributes, ULONG ShareAccess, ULONG CreateDisposition, ULONG CreateOptions, PVOID EaBuffer, ULONG EaLength);
DWORD NTSockets_CreateTcpSocket(struct NTSockets_SocketDataStruct
*
pSocketData,
int
bTcp)
{
struct IO_STATUS_BLOCK IoStatusBlock;
HANDLE hEvent
=
NULL;
HANDLE hSocket
=
NULL;
struct OBJECT_ATTRIBUTES ObjectAttributes;
struct NTSockets_SocketDataStruct SocketData;
struct UNICODE_STRING ObjectFilePath;
DWORD dwStatus
=
0
;
/
*
tcp extended attr
0x0000003395EFF130
00
00
00
00
00
0f
1e
00
41
66
64
4f
70
65
6e
50
........AfdOpenP
0x0000003395EFF140
61
63
6b
65
74
58
58
00
00
00
00
00
00
00
00
00
acketXX.........
0x0000003395EFF150
02
00
00
00
01
00
00
00
06
00
00
00
00
00
00
00
................
0x0000003395EFF160
08
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
................
*
/
/
*
udp
0x000000506EF3F040
00
00
00
00
00
0f
1e
00
41
66
64
4f
70
65
6e
50
........AfdOpenP
0x000000506EF3F050
61
63
6b
65
74
58
58
00
11
00
00
00
00
00
00
00
acketXX.........
0x000000506EF3F060
02
00
00
00
02
00
00
00
11
00
00
00
00
00
00
00
................
0x000000506EF3F070
08
01
00
00
00
00
00
00
00
00
00
00
00
00
00
00
................
*
/
BYTE bEaUdp[]
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x0f
,
0x1e
,
0x00
,
0x41
,
0x66
,
0x64
,
0x4f
,
0x70
,
0x65
,
0x6e
,
0x50
,
0x61
,
0x63
,
0x6b
,
0x65
,
0x74
,
0x58
,
0x58
,
0x00
,
0x11
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x11
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x08
,
0x01
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
};
BYTE bExtendedAttributes[]
=
{
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x0F
,
0x1E
,
0x00
,
0x41
,
0x66
,
0x64
,
0x4F
,
0x70
,
0x65
,
0x6E
,
0x50
,
0x61
,
0x63
,
0x6B
,
0x65
,
0x74
,
0x58
,
0x58
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x02
,
0x00
,
0x00
,
0x00
,
0x01
,
0x00
,
0x00
,
0x00
,
0x06
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x00
,
0x60
,
0xEF
,
0x3D
,
0x47
,
0xFE
};
printf(
"[*] NTSockets_CreateTcpSocket:: is %s !\n"
,bTcp ?
"TCP"
:
"UDP"
);
struct FILE_FULL_EA_INFORMATION
*
ffe;
ffe
=
(struct FILE_FULL_EA_INFORMATION
*
)bTcp ? bExtendedAttributes : bEaUdp;
/
/
create status event
hEvent
=
CreateEvent(NULL,
0
,
0
, NULL);
if
(hEvent
=
=
NULL)
{
/
/
error
return
1
;
}
/
/
set
afd endpoint path
memset((void
*
)&ObjectFilePath,
0
, sizeof(ObjectFilePath));
ObjectFilePath.
Buffer
=
L
"\\Device\\Afd\\Endpoint"
;
ObjectFilePath.Length
=
wcslen(ObjectFilePath.
Buffer
)
*
sizeof(wchar_t);
ObjectFilePath.MaximumLength
=
ObjectFilePath.Length;
/
/
initialise
object
attributes
memset((void
*
)&ObjectAttributes,
0
, sizeof(ObjectAttributes));
ObjectAttributes.Length
=
sizeof(ObjectAttributes);
ObjectAttributes.ObjectName
=
&ObjectFilePath;
ObjectAttributes.Attributes
=
0x40
;
/
/
create socket handle
IoStatusBlock.Status
=
0
;
IoStatusBlock.Information
=
NULL;
dwStatus
=
NtCreateFile(&hSocket,
0xC0140000
, &ObjectAttributes, &IoStatusBlock, NULL,
0
, FILE_SHARE_READ | FILE_SHARE_WRITE,
1
,
0
, ffe, sizeof(bExtendedAttributes));
if
(dwStatus !
=
0
)
{
/
/
error
CloseHandle(hEvent);
return
1
;
}
/
/
initialise SocketData
object
memset((void
*
)&SocketData,
0
, sizeof(SocketData));
SocketData.hSocket
=
hSocket;
SocketData.hStatusEvent
=
hEvent;
/
/
store socket data
memcpy((void
*
)pSocketData, (void
*
)&SocketData, sizeof(SocketData));
return
0
;
}
DWORD NTSockets_SocketDriverMsg(struct NTSockets_SocketDataStruct
*
pSocketData, DWORD dwIoControlCode, BYTE
*
pData, DWORD dwLength, DWORD
*
pdwOutputInformation)
{
struct IO_STATUS_BLOCK IoStatusBlock;
DWORD dwStatus
=
0
;
BYTE bOutputBlock[
0x10
];
/
/
reset status event
ResetEvent(pSocketData
-
>hStatusEvent);
/
/
send device control request
IoStatusBlock.Status
=
0
;
IoStatusBlock.Information
=
NULL;
dwStatus
=
NtDeviceIoControlFile(pSocketData
-
>hSocket, pSocketData
-
>hStatusEvent, NULL, NULL, &IoStatusBlock, dwIoControlCode, (void
*
)pData, dwLength, bOutputBlock, sizeof(bOutputBlock));
if
(dwStatus
=
=
STATUS_PENDING)
{
/
/
response pending
-
wait
for
event
if
(WaitForSingleObject(pSocketData
-
>hStatusEvent,
-
1
) !
=
WAIT_OBJECT_0)
{
/
/
error
return
1
;
}
/
/
complete
-
get final status code
dwStatus
=
IoStatusBlock.Status;
}
/
/
check
for
errors
if
(dwStatus !
=
0
)
{
/
/
error
return
1
;
}
if
(pdwOutputInformation !
=
NULL)
{
/
/
store output info
*
pdwOutputInformation
=
(DWORD)IoStatusBlock.Information;
}
return
0
;
}
DWORD NTSockets_ConvertIP(char
*
pIP, DWORD
*
pdwAddr)
{
char szCurrOctet[
8
];
DWORD dwCurrOctetIndex
=
0
;
DWORD dwCompletedOctetCount
=
0
;
char
*
pCurrByte
=
NULL;
DWORD dwEndOfOctet
=
0
;
DWORD dwEndOfString
=
0
;
DWORD dwOctet
=
0
;
BYTE bOctets[
4
];
DWORD dwAddr
=
0
;
/
/
read IP string
memset(szCurrOctet,
0
, sizeof(szCurrOctet));
dwCurrOctetIndex
=
0
;
pCurrByte
=
pIP;
for
(;;)
{
/
/
process current character
dwEndOfOctet
=
0
;
if
(
*
pCurrByte
=
=
'\0'
)
{
/
/
end of string
dwEndOfOctet
=
1
;
dwEndOfString
=
1
;
}
else
if
(
*
pCurrByte
=
=
'.'
)
{
/
/
end of octet
dwEndOfOctet
=
1
;
}
else
{
/
/
ensure this character
is
a number
if
(
*
pCurrByte >
=
'0'
&&
*
pCurrByte <
=
'9'
)
{
if
(dwCurrOctetIndex >
2
)
{
/
/
invalid ip
return
1
;
}
/
/
store current character
szCurrOctet[dwCurrOctetIndex]
=
*
pCurrByte;
dwCurrOctetIndex
+
+
;
}
else
{
/
/
invalid ip
return
1
;
}
}
/
/
check
if
the current octet
is
complete
if
(dwEndOfOctet !
=
0
)
{
if
(dwCurrOctetIndex
=
=
0
)
{
/
/
invalid ip
return
1
;
}
/
/
convert octet string to integer
dwOctet
=
atoi(szCurrOctet);
if
(dwOctet >
255
)
{
/
/
invalid ip
return
1
;
}
/
/
already read
4
octets
if
(dwCompletedOctetCount >
=
4
)
{
/
/
invalid ip
return
1
;
}
/
/
store current octet
bOctets[dwCompletedOctetCount]
=
(BYTE)dwOctet;
/
/
current octet complete
dwCompletedOctetCount
+
+
;
if
(dwEndOfString !
=
0
)
{
/
/
end of string
break
;
}
/
/
reset szCurrOctet string
memset(szCurrOctet,
0
, sizeof(szCurrOctet));
dwCurrOctetIndex
=
0
;
}
/
/
move to the
next
character
pCurrByte
+
+
;
}
/
/
ensure
4
octets were found
if
(dwCompletedOctetCount !
=
4
)
{
/
/
invalid string
return
1
;
}
/
/
store octets
in
dword value
memcpy((void
*
)&dwAddr, bOctets,
4
);
/
/
store value
*
pdwAddr
=
dwAddr;
return
0
;
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
最后于 2022-5-27 23:21
被zhenwo编辑
,原因: 完善测试代码