fork download
  1. #include <iostream>
  2. using namespace std;
  3.  
  4. #include <stdio.h>
  5. #include <stdint.h>
  6. #include <inttypes.h> //PRIx64
  7.  
  8. #define BOOST_STATIC_ASSERT(x)
  9.  
  10. // #define _ULONGLONG_
  11. // #if (!defined (_MAC) && (!defined(MIDL_PASS) || defined(__midl)) && (!defined(_M_IX86) || (defined(_INTEGRAL_MAX_BITS) && _INTEGRAL_MAX_BITS >= 64)))
  12. // typedef __int64 LONGLONG;
  13. // typedef unsigned __int64 ULONGLONG;
  14.  
  15. // #define MAXLONGLONG (0x7fffffffffffffff)
  16.  
  17.  
  18. // #else
  19.  
  20. // #if defined(_MAC) && defined(_MAC_INT_64)
  21. // typedef __int64 LONGLONG;
  22. // typedef unsigned __int64 ULONGLONG;
  23.  
  24. // #define MAXLONGLONG (0x7fffffffffffffff)
  25.  
  26.  
  27. // #else
  28. // typedef double LONGLONG;
  29. // typedef double ULONGLONG;
  30. // #endif //_MAC and int64
  31.  
  32. // #endif
  33.  
  34.  
  35. // #ifndef VOID
  36. // #define VOID void
  37. // typedef char CHAR;
  38. // typedef short SHORT;
  39. // typedef long LONG;
  40. // #if !defined(MIDL_PASS)
  41. // typedef int INT;
  42. // #endif
  43. // #endif
  44.  
  45. // typedef unsigned long DWORD;
  46.  
  47. // #if defined(MIDL_PASS)
  48. // typedef struct _LARGE_INTEGER {
  49. // #else // MIDL_PASS
  50. // typedef union _LARGE_INTEGER {
  51. // struct {
  52. // DWORD LowPart;
  53. // LONG HighPart;
  54. // } DUMMYSTRUCTNAME;
  55. // struct {
  56. // DWORD LowPart;
  57. // LONG HighPart;
  58. // } u;
  59. // #endif //MIDL_PASS
  60. // LONGLONG QuadPart;
  61. // } LARGE_INTEGER;
  62.  
  63. //typedef LARGE_INTEGER *PLARGE_INTEGER;
  64.  
  65. // /* BASETYPES is defined in ntdef.h if these types are already defined */
  66. // #ifndef BASETYPES
  67. // #define BASETYPES
  68. // typedef unsigned long ULONG;
  69. // typedef ULONG *PULONG;
  70. // typedef unsigned short USHORT;
  71. // typedef USHORT *PUSHORT;
  72. // typedef unsigned char UCHAR;
  73. // typedef UCHAR *PUCHAR;
  74. // //typedef _Null_terminated_ char *PSZ;
  75. // #endif /* !BASETYPES */
  76.  
  77. /* Basic system type definitions, taken from the BSD file sys/types.h. */
  78. typedef unsigned char u_char;
  79. typedef unsigned short u_short;
  80. typedef unsigned int u_int;
  81. typedef unsigned long u_long;
  82.  
  83. typedef char CCHAR;
  84.  
  85. // #ifndef _MAC
  86. // typedef wchar_t WCHAR; // wc, 16-bit UNICODE character
  87. // #else
  88. // // some Macintosh compilers don't define wchar_t in a convenient location, or define it as a char
  89. // typedef unsigned short WCHAR; // wc, 16-bit UNICODE character
  90. // #endif
  91. //typedef char32_t WCHAR;
  92. typedef int16_t WCHAR;
  93.  
  94. typedef uint32_t ULONG;
  95. typedef uint32_t DWORD;
  96. typedef uint64_t LARGE_INTEGER;
  97.  
  98. #ifdef __cplusplus
  99. # define STATIC_CAST(T, x) static_cast<T>(x)
  100. # define REINTERPRET_CAST(T, x) reinterpret_cast<T>(x)
  101. # define CONST_CAST(T, x) const_cast<T>(x)
  102. #else
  103. # define STATIC_CAST(T, x) ((T)(x))
  104. # define REINTERPRET_CAST(T, x) ((T)(x))
  105. # define CONST_CAST(T, x) ((T)(x))
  106. #endif
  107.  
  108. #pragma pack(1)
  109. /**
  110. * [MS-SMB2] 2.2.33 SMB2 QUERY_DIRECTORY Request (CommandCode = 14 , BodySize = 33 )
  111. * The SMB2 QUERY_DIRECTORY Request packet is sent by the client to obtain a directory enumeration on a directory open. This request consists of an SMB2 header, as specified in section 2.2.1, followed by this request structure:
  112. */
  113. typedef struct {
  114. /* StructureSize (2 bytes): The client MUST set this field to 33, indicating the size of the request structure, not including the header. The client MUST set this field to this value regardless of how long Buffer[] actually is in the request being sent. */
  115. uint16_t StructureSize;
  116. /**
  117. * FileInformationClass (1 byte): The file information class describing the format that data MUST be returned in.
  118. * Possible values are as specified in [MS-FSCC] section 2.4 File Information Classes. This field MUST contain
  119. * one of the following values:
  120. * * **FileDirectoryInformation** 0x01 Basic information about a file or directory. Basic information is defined
  121. * as the file's name, time stamp, size and attributes. File attributes are as specified in [MS-FSCC] section
  122. * 2.6 File Attributes.
  123. * * **FileFullDirectoryInformation** 0x02 Full information about a file or directory. Full information is defined
  124. * as all the basic information plus extended attribute size.
  125. * * **FileIdFullDirectoryInformation** 0x26 Full information plus volume file ID about a file or directory. A
  126. * volume file ID is defined as a number assigned by the underlying object store that uniquely identifies a file
  127. * within a volume.
  128. * * **FileBothDirectoryInformation** 0x03 Basic information plus extended attribute size and short name about a
  129. * file or directory. See [MS-FSCC] 2.4.17 FileIdBothDirectoryInformation or FILE_ID_BOTH_DIR_INFORMATION structure in ntifs.h
  130. * * **FileIdBothDirectoryInformation** 0x25 FileBothDirectoryInformation plus volume file ID about a file or directory.
  131. * * **FileNamesInformation** 0x0C Detailed information on the names of files and directories in a directory.
  132. * @see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/4718fc40-e539-4014-8e33-b675af74e3e1#24-file-information-classes
  133. * @see https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/wdm/ne-wdm-_file_information_class
  134. */
  135. u_char FileInformationClass;
  136. u_char Flags; /* Flags (1 byte): Flags indicating how the query directory operation MUST be processed. This field MUST be a logical OR of the following values, or zero if none are selected: */
  137. /* FileIndex (4 bytes): The byte offset within the directory, indicating the position at which to resume the enumeration. If SMB2_INDEX_SPECIFIED is set in Flags, this value MUST be supplied and is based on the FileIndex value received in a previous enumeration response. Otherwise, it MUST be set to zero and the server MUST ignore it. */
  138. uint32_t FileIndex;
  139. /* FileId (16 bytes): An SMB2_FILEID identifier of the directory on which to perform the enumeration. This is returned from an SMB2 Create Request to open a directory on the server. */
  140. u_char FileId[16];
  141. /* FileNameOffset (2 bytes): The offset, in bytes, from the beginning of the SMB2 header to the search pattern to be used for the enumeration. This field MUST be 0 if no search pattern is provided. */
  142. uint16_t FileNameOffset;
  143. /* FileNameLength (2 bytes): The length, in bytes, of the search pattern. This field MUST be 0 if no search pattern is provided. */
  144. uint16_t FileNameLength;
  145. /* OutputBufferLength (4 bytes): The maximum number of bytes the server is allowed to return in the SMB2 QUERY_DIRECTORY Response. */
  146. uint32_t OutputBufferLength;
  147. /* Buffer (variable): A variable-length buffer containing the Unicode search pattern for the request, as described by the FileNameOffset and FileNameLength fields. The format, including wildcards and other conventions for this pattern, is specified in [MS-CIFS] section 2.2.1.1.3.<65> */
  148. u_char Buffer[];
  149. } smb2_query_directory_request_t;
  150. BOOST_STATIC_ASSERT(32 == sizeof(smb2_query_directory_request_t));
  151.  
  152. /**
  153. This information class differs from FileDirectoryInformation (section 2.4.10) in that it includes short names in the returns list.
  154. @see https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-fscc/270df317-9ba5-4ccb-ba00-8d22be139bc5#248-filebothdirectoryinformation
  155. @see https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/content/ntifs/ns-ntifs-_file_id_both_dir_information
  156. */
  157. typedef struct smb2_FileBothDirectoryInformation {
  158. /* NextEntryOffset (4 bytes): A 32-bit unsigned integer that contains the byte offset from the beginning of this entry, at which the next FILE_BOTH_DIR_INFORMATION entry is located, if multiple entries are present in a buffer. This member is zero if no other entries follow this one. An implementation MUST use this value to determine the location of the next entry (if multiple entries are present in a buffer). */
  159. ULONG NextEntryOffset;
  160. /* FileIndex (4 bytes): A 32-bit unsigned integer that contains the byte offset of the file within the parent directory. For file systems in which the position of a file within the parent directory is not fixed and can be changed at any time to maintain sort order, this field SHOULD be set to 0x00000000 and MUST be ignored.<89> */
  161. ULONG FileIndex;
  162. /* CreationTime (8 bytes): The time when the file was created; see section 2.1.1. This value MUST be greater than or equal to 0. */
  163. LARGE_INTEGER CreationTime;
  164. /* LastAccessTime (8 bytes): The last time the file was accessed; see section 2.1.1. This value MUST be greater than or equal to 0. */
  165. LARGE_INTEGER LastAccessTime;
  166. /* LastWriteTime (8 bytes): The last time information was written to the file; see section 2.1.1. This value MUST be greater than or equal to 0. */
  167. LARGE_INTEGER LastWriteTime;
  168. /* ChangeTime (8 bytes): The last time the file was changed; see section 2.1.1. This value MUST be greater than or equal to 0. */
  169. LARGE_INTEGER ChangeTime;
  170. /* EndOfFile (8 bytes): A 64-bit signed integer that contains the absolute new end-of-file position as a byte offset from the start of the file. EndOfFile specifies the offset to the byte immediately following the last valid byte in the file. Because this value is zero-based, it actually refers to the first free byte in the file. That is, it is the offset from the beginning of the file at which new bytes appended to the file will be written. The value of this field MUST be greater than or equal to 0. */
  171. LARGE_INTEGER EndOfFile;
  172. /* AllocationSize (8 bytes): A 64-bit signed integer that contains the file allocation size, in bytes. The value of this field MUST be an integer multiple of the cluster size. */
  173. LARGE_INTEGER AllocationSize;
  174. /* FileAttributes (4 bytes): A 32-bit unsigned integer that contains the file attributes. Valid file attributes are specified in section 2.6. */
  175. ULONG FileAttributes;
  176. /* FileNameLength (4 bytes): A 32-bit unsigned integer that specifies the length, in bytes, of the file name contained within the FileName member. */
  177. ULONG FileNameLength;
  178. /* EaSize (4 bytes): A 32-bit unsigned integer that contains the combined length, in bytes, of the extended attributes (EA) for the file. */
  179. ULONG EaSize;
  180. /* ShortNameLength (1 byte): An 8-bit signed integer that specifies the length, in bytes, of the file name contained in the ShortName member. This value MUST be greater than or equal to 0. */
  181. CCHAR ShortNameLength;
  182. /* Reserved (1 byte): Reserved for alignment. This field can contain any value and MUST be ignored. */
  183. CCHAR Reserved;
  184. /* ShortName (24 bytes): A sequence of Unicode characters containing the short (8.3) file name. When working with this field, use ShortNameLength to determine the length of the file name rather than assuming the presence of a trailing null delimiter. */
  185. WCHAR ShortName[12];
  186. /* The 8-byte file reference number for the file. This number is generated and assigned to the file by the file system. (Note that the FileId is not the same as the 16-byte "file object ID" that was added to NTFS for Microsoft Windows 2000.) */
  187. LARGE_INTEGER FileId; // Missing in [MS-FSCC]: File System Control Codes - 2.4.8 FileBothDirectoryInformation
  188. u_char Reserved2[2]; // Missing in [MS-FSCC]: File System Control Codes - 2.4.8 FileBothDirectoryInformation
  189. /* FileName (variable): A sequence of Unicode characters containing the file name. When working with this field, use FileNameLength to determine the length of the file name rather than assuming the presence of a trailing null delimiter. Dot directory names are valid for this field. For more details, see section 2.1.5.1. */
  190. WCHAR FileName[1];
  191. } smb2_FileBothDirectoryInformation_t;
  192. BOOST_STATIC_ASSERT(106 == sizeof(smb2_FileBothDirectoryInformation_t));
  193.  
  194. /**
  195. * [MS-SMB2] 2.2.34 SMB2 QUERY_DIRECTORY Response (CommandCode = 14 , BodySize = 9 + variable)
  196. * The SMB2 QUERY_DIRECTORY Response packet is sent by a server in response to an SMB2 QUERY_DIRECTORY Request (section 2.2.33). This response consists of an SMB2 header, as specified in section 2.2.1, followed by this response structure:
  197. */
  198. typedef struct {
  199. /*
  200. StructureSize (2 bytes): The server MUST set this field to 9, indicating the size of the request structure, not including the header.
  201. The server MUST set this field to this value regardless of how long Buffer[] actually is in the request.
  202. */
  203. uint16_t StructureSize;
  204. /* OutputBufferOffset (2 bytes): The offset, in bytes, from the beginning of the SMB2 header to the directory enumeration data being returned. */
  205. uint16_t OutputBufferOffset;
  206. /* OutputBufferLength (4 bytes): The length, in bytes, of the directory enumeration being returned. */
  207. uint32_t OutputBufferLength;
  208. /*
  209. Buffer (variable): A variable-length buffer containing the directory enumeration being returned in the response,
  210. as described by the OutputBufferOffset and OutputBufferLength. The format of this content is as specified in
  211. [MS-FSCC] section 2.4 File Information Classes, within the topic for the specific file information class referenced
  212. in the SMB2 QUERY_DIRECTORY Request. */
  213. u_char Buffer[1];
  214. } smb2_query_directory_response_t;
  215. BOOST_STATIC_ASSERT(9 == sizeof(smb2_query_directory_response_t));
  216.  
  217. #pragma pack()
  218.  
  219.  
  220. //https://stackoverflow.com/questions/15934111/portable-and-safe-way-to-add-byte-offset-to-any-pointer
  221. template <typename T> inline void addOffset(std::ptrdiff_t offset, T *&ptr) {
  222. if (!ptr) return;
  223. ptr = (T*)((const unsigned char*)ptr + offset);
  224. }
  225. template <typename T> inline T* offset(std::ptrdiff_t offset, T *ptr) {
  226. return (T*)((const unsigned char*)ptr + offset);
  227. }
  228. //SomeType* ptr; int offset = 12345; offset_ptr(offset, ptr);
  229. template <typename T> inline void offset_ptr(std::ptrdiff_t byte_offset, const T* &ref_ptr) {
  230. ref_ptr = (T*)((const unsigned char*)ref_ptr + byte_offset);
  231. }
  232.  
  233. //If you use this marco like `typedef struct {} SomeType; SomeType* ptr; OFFSET_PTR(16, ptr);`
  234. //IDE error: expression must be a modifiable value. Compile: error C2106: '=': left operand must be l-value.
  235. #define OFFSET_PTR(byte_offset, ref_ptr) ((const unsigned char*)ref_ptr = (const unsigned char*)ref_ptr + byte_offset)
  236.  
  237.  
  238. char packet_bytes[9] = {0};
  239.  
  240. int main(int argc, char* argv[]) {
  241. printf("(int)sizeof(smb2_query_directory_response_t) = %d\n", (int)sizeof(smb2_query_directory_response_t));
  242. printf("(int)sizeof(smb2_FileBothDirectoryInformation_t) = %d\n", (int)sizeof(smb2_FileBothDirectoryInformation_t));
  243.  
  244. const smb2_query_directory_response_t* pSMB2QueryDirectoryResponse = (smb2_query_directory_response_t*)packet_bytes;
  245. const smb2_FileBothDirectoryInformation_t *pFileBothDirInfo = pSMB2QueryDirectoryResponse->OutputBufferLength ? REINTERPRET_CAST(const smb2_FileBothDirectoryInformation_t*, pSMB2QueryDirectoryResponse->Buffer) : NULL;
  246. while (pFileBothDirInfo)
  247. {
  248. // ideone runs on linux with a compiler who consider wchar_t 4 bytes?
  249. // https://stackoverflow.com/questions/16944750/c-unicode-characters-printing
  250. //wprintf(L"%.*s|%.*s\n", pFileBothDirInfo->FileNameLength/2, pFileBothDirInfo->FileName, pFileBothDirInfo->ShortNameLength/2, pFileBothDirInfo->ShortName);
  251. if (pFileBothDirInfo->NextEntryOffset)
  252. {
  253. offset_ptr(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo);
  254.  
  255. const unsigned char *ptrTemp;
  256. ptrTemp = ((const unsigned char*)pFileBothDirInfo + 10);
  257. //be equivalent to
  258. //((const unsigned char*)pFileBothDirInfo) = ( (const unsigned char*)pFileBothDirInfo + 10 );
  259. OFFSET_PTR(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo);
  260.  
  261. printf("ptrTemp = %p", ptrTemp);
  262. }
  263. else
  264. {
  265. break;
  266. }
  267. }
  268. return 0;
  269. }
Compilation error #stdin compilation error #stdout 0s 15232KB
stdin
Standard input is empty
compilation info
prog.cpp: In function ‘int main(int, char**)’:
prog.cpp:259:33: error: lvalue required as left operand of assignment
    OFFSET_PTR(pFileBothDirInfo->NextEntryOffset, pFileBothDirInfo);
                                 ^
prog.cpp:235:107: note: in definition of macro ‘OFFSET_PTR’
 #define OFFSET_PTR(byte_offset, ref_ptr) ((const unsigned char*)ref_ptr = (const unsigned char*)ref_ptr + byte_offset)
                                                                                                           ^~~~~~~~~~~
stdout
Standard output is empty